[解決済み] Java8でvoid(Voidではない)メソッドに関数型を指定する方法は?
質問
Java 8 を使って、関数がどのようにファーストクラス市民として扱われるかを調べているところです。次のようなスニペットがあります。
package test;
import java.util.*;
import java.util.function.*;
public class Test {
public static void myForEach(List<Integer> list, Function<Integer, Void> myFunction) {
list.forEach(functionToBlock(myFunction));
}
public static void displayInt(Integer i) {
System.out.println(i);
}
public static void main(String[] args) {
List<Integer> theList = new ArrayList<>();
theList.add(1);
theList.add(2);
theList.add(3);
theList.add(4);
theList.add(5);
theList.add(6);
myForEach(theList, Test::displayInt);
}
}
私がやろうとしていることは、メソッドを渡すことです。
displayInt
をメソッドに
myForEach
をメソッド参照で使用します。コンパイラは次のようなエラーを出します。
src/test/Test.java:9: error: cannot find symbol
list.forEach(functionToBlock(myFunction));
^
symbol: method functionToBlock(Function<Integer,Void>)
location: class Test
src/test/Test.java:25: error: method myForEach in class Test cannot be applied to given ty
pes;
myForEach(theList, Test::displayInt);
^
required: List<Integer>,Function<Integer,Void>
found: List<Integer>,Test::displayInt
reason: argument mismatch; bad return type in method reference
void cannot be converted to Void
コンパイラは次のような文句を言います。
void cannot be converted to Void
. のシグネチャで関数インターフェイスの型を指定する方法がわかりません。
myForEach
このような場合、コードはコンパイルされます。の戻り値の型を単純に変更することができるのは知っています。
displayInt
を
Void
を返し、さらに
null
. しかし、渡したいメソッドをどこかに変更することができない状況もあるかもしれません。を簡単に再利用する方法はないでしょうか?
displayInt
をそのまま使うのでしょうか?
解決方法は?
間違ったインターフェースの種類を使おうとしています。そのタイプは 機能 は、パラメータを受け取り、戻り値を持つので、この場合適切ではありません。代わりに 消費者 (旧名ブロック)
関数型は次のように宣言されています。
interface Function<T,R> {
R apply(T t);
}
しかし、Consumerタイプは、あなたが探しているものと互換性があります。
interface Consumer<T> {
void accept(T t);
}
このように、ConsumerはTを受け取って何も返さない(void)メソッドと互換性があります。そして、これはあなたが望んでいることです。
例えば、リスト内の全ての要素を表示したい場合は、ラムダ式でコンシューマを作ればいい。
List<String> allJedi = asList("Luke","Obiwan","Quigon");
allJedi.forEach( jedi -> System.out.println(jedi) );
この場合、ラムダ式はパラメータを受け取り、戻り値を持たないことが上記でおわかりいただけると思います。
さて、このタイプのconsumeを作るのにラムダ式の代わりにメソッド参照を使いたかったら、Stringを受け取ってvoidを返すメソッドが必要ですよね?
別の種類のメソッド参照を使うこともできますが、今回はオブジェクトのメソッド参照を利用することにしましょう。
println
メソッドを
System.out
オブジェクトをこのように使用します。
Consumer<String> block = System.out::println
あるいは、単純に
allJedi.forEach(System.out::println);
は
println
メソッドは、値を受け取り、戻り値の型が void であるため、適切なものです。
accept
というメソッドがあります。
ですから、あなたのコードでは、メソッドのシグネチャを多少なりとも変更する必要があるのです。
public static void myForEach(List<Integer> list, Consumer<Integer> myBlock) {
list.forEach(myBlock);
}
そして、静的メソッドの参照を使用して、あなたの場合はこうすることで、コンシューマを作成できるようになるはずです。
myForEach(theList, Test::displayInt);
最終的には、あなたの
myForEach
メソッドを完全に削除し、単純に実行します。
theList.forEach(Test::displayInt);
ファーストクラスシチズンとしての機能について
というのも、構造的な関数型が言語に追加されるわけではないからです。Javaは、ラムダ式とメソッド参照から関数型インターフェースの実装を作成するための代替方法を提供するだけです。最終的には、ラムダ式とメソッド参照はオブジェクト参照に束縛されるでしょうから、私たちが手にするのは一級市民としてのオブジェクトだけです。重要なのは、オブジェクトをパラメータとして渡したり、変数参照に束縛したり、他のメソッドから値として返したりできるため、機能的にはほとんど同じであることだ。
関連
-
Java Error スレッド "AWT-EventQueue-0" で例外発生 java.lang.
-
スタイルシートとして解釈されるリソースが、MIMEタイプtext/htmlで転送される。
-
Dateが型に解決できない問題を解決する
-
Intellij IDEAのエラー「CreateProcess error=2, system could not find specified file」に対する完璧な解決策です。
-
マスキング このリソースにアクセスするには、完全な認証が必要です。
-
linux run jarfile Invalid or corrupt jarfile error.
-
javax.net.ssl.SSLException: 読み取りエラー: ssl=0xdeae5100: システムコール中の I/O エラー、接続 res
-
[解決済み] プライベートメソッド、フィールド、インナークラスを持つクラスをテストするにはどうすればよいですか?
-
[解決済み] Javaの「for each」ループはどのように機能するのですか?
-
[解決済み] Mockitoでvoidメソッドをモックする方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
スタイルが読み込まれず、ブラウザのコンソールでエラーが報告される。リソースはスタイルシートとして解釈されますが、MIMEタイプtext/htmlで転送されます。
-
java の例外が発生しました java
-
コンストラクタの呼び出しは、コンストラクタのエラー理解の最初のステートメントである必要があります。
-
java Mail send email smtp is not authenticated by TLS encryption solution.
-
VMの初期化中にエラーが発生しました java/lang/NoClassDefFoundError: java/lang/Object
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a
-
JSPで「リストが型解決できない!」の解決方法
-
ブラウザでの大容量ファイルスライスアップロード(Javaサーバサイド実装)
-
[解決済み] Javaにおけるコールバック関数
-
[解決済み】Java 8 lambda Void 引数