2014年11月3日月曜日

[Java8]メソッド参照

lambda式で定義したい処理内容と全く同じ処理をするメソッドがすでに提供されている場合には、
そのメソッドをメソッド参照という機能を使用してメソッドを渡してあげれば良い。

メソッド参照は、以下のように::演算子でクラス名(オブジェクト名)とメソッド名を連結して使用する。
使用できるパターンは、以下のとおり。

* オブジェクト::instanceメソッド
* クラス名::staticメソッド
* クラス名::instanceメソッド

使用例

System.out.printlnを使用した例は以下のようになる。
list.forEach(System.out::println);

// 上記は、以下と全く同じ
list.forEach(s -> System.out.println(s));

オーバロードされたメソッドがある場合

メソッド参照使用時で、オーバロードされたメソッドが存在していた場合にどのメソッドを呼びだそうとしているかについては、コンパイラがコードの内容から判断しようとする。

例えば、以下の例だとメソッド参照が使用された箇所の関数型インタフェースが受け取る型に対応したメソッドが使用される。

public class Hoge {

    public static void main(String[] args) {
        List strings = Arrays.asList("1", "2", "3");
        strings.forEach(Hoge::output);  // Stringを引数に取るoutputが選択される

        List numbers = Arrays.asList(1, 2, 3);
        numbers.forEach(Hoge::output);  // intを引数に取るoutputが選択される
    }

    public static void output(String s) {
        System.out.println("string");
    }

    public static void output(int i) {
        System.out.println("int");
    }
}

2014年11月2日日曜日

[Java8]Lambda式の形式

ラムダ式は、引数 -> 式本体の形式で記述する。

基本パターン

(String first, String second) -> {
  return Integer.compare(first.length, second.length)
}

型推論可能な場合は、引数の型を省略出来る

左辺の総称型などから推論可能な場合などに型推論される。
(first, second) -> {
  return Integer.compare(first.length, second.length)
}

型推論された引数を一つだけ保つ場合には、カッコも省略可能

Arrays.asList(1, 2, 3, 4, 5).forEach(n -> System.out.println(n));

アノテーションなど

メソッドの引数と同じように、、アノテーションやfinal修飾子をつけることも可能
(final String first, final String second) -> {
  return Integer.compare(first.length, second.length)
}

戻り値について

lambdaの戻り値は明示しない。常に文脈から型が判断される。
以下の例だとintが期待されているところで使用できる。

※分岐などで結果を返したり返さなかったりするようなlambda式は不正となる。(コンパイルエラー)
(final String first, final String second) -> {
  return Integer.compare(first.length, second.length)
}