公式チュートリアルの「ターゲット型付け」セクションを読む
前回ポストのあとOracleの公式チュートリアル"The Java Tutorials"の"Nested Classes" > "Lambda Expressions"に含まれるセクション"Target Typing"を読んでみました。ターゲット型とターゲット型付けという概念の理解のため若干の助けになるかと思います。
* * *
ターゲット型付け
ラムダ式の型はどのように決定されるのでしょうか? 先ほど〔Person
のコレクションの中から〕「性別は男性で年齢が18〜25才の間の人」を抽出するのに使用されたラムダ式を思い出してみてください:
p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25
public static void printPersons(List< Person> roster, CheckPerson tester)
──これはアプローチ3「ローカルクラスで検索条件コードを指定する」で登場しました〔訳注:このセクションではCheckPersonというインターフェースとそれを実装するインナークラスが宣言されています。このクラスのメソッドの実装部には上述のラムダ式に相当するロジックが記述されています。そしてセクションの終盤でこのクラスの代わりにラムダ式が導入されます〕。public void printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester)
──これはアプローチ6「ラムダ式で標準の関数型インターフェースを使う」で登場しました〔訳注:このセクションではPredicate<T>というjava.util.functionパッケージに所属する標準の関数型インターフェースに適合するかたちでラムダ式が宣言され引数として設定されています〕。
Javaランタイムが printPersons
メソッドを呼び出すとき、引数として CheckPerson
型のデータが渡されることが期待されています。このためラムダ式はその型になります。一方、Javaランタイムが printPersonsWithPredicate
メソッドを呼び出すとき、引数として Predicate< Person>
型のデータが渡されることが期待されています。このためラムダ式はその型になります。このメソッドが期待するデータ型を「ターゲット型」と呼びます。ラムダ式のデータ型の決定のため、Javaコンパイラは当該のラムダ式が置かれた文脈や状況におけるターゲット型を利用します。このためラムダ式が使える状況というのは、Javaコンパイラがターゲット型を決定できる状況に限定されます:
ターゲット型とメソッド引数
メソッド引数のため、Javaコンパイラはそのターゲット型を決定します。これには他の2つの言語機能が関与します。それは多重定義解決〔多重定義されたメソッドのいずれを実行するかの決定〕と型引数推論〔省略された型パラメータの推論〕です。
次の2つの関数型インターフェースについて考えてみてください(java.lang.Runnable
とjava.util.concurrent.Callable< V>
):
public interface Runnable { void run(); } public interface Callable<V> { V call(); }
Runnable.run
メソッドは値を返しません。対して Callable
メソッドは値を返します。
ここであなたは次のようなinvoke
メソッドを用意しているとしましょう(メソッドの多重定義についてより詳しく知りたい方は「メソッドを定義する」のセクションを参照してください)。
void invoke(Runnable r) { r.run(); } <T> T invoke(Callable<T> c) { return c.call(); }
さて、次の構文ではいずれのメソッドが呼び出されるのでしょうか?
String s = invoke(() -> "done");
invoke(Callable< T>)
が呼び出されるでしょう。なぜならこのメソッドは値を返すメソッドだからです。対してinvoke(Runnable)
はそうではありません。この場合、ラムダ式 () -> "done"
の型は Callable<T>
になります。
* * *
原典は、Oracleの公式チュートリアル"The Java Tutorials"の"Nested Classes" > "Lambda Expressions"に含まれるセクション"Target Typing"です。