1. 概要

この簡単な記事では、Java 8のダブルコロン演算子 :: )について説明し、演算子を使用できるシナリオについて説明します。

2. ラムダからダブルコロン演算子まで

Lambdas式を使用すると、コードが非常に簡潔になる可能性があることがわかりました。

たとえば、コンパレータを作成するには、次の構文で十分です。

Comparator c = (Computer c1, Computer c2) -> c1.getAge().compareTo(c2.getAge());

次に、型推論を使用します。

Comparator c = (c1, c2) -> c1.getAge().compareTo(c2.getAge());

しかし、上記のコードをさらに表現力豊かで読みやすくすることはできますか? みてみましょう:

Comparator c = Comparator.comparing(Computer::getAge);

名前で特定のメソッドを呼び出すラムダの省略形として、::演算子を使用しました。 そして最後に、結果はもちろんさらに読みやすい構文になります。

3. それはどのように機能しますか?

非常に簡単に言えば、メソッド参照を使用している場合、ターゲット参照は区切り文字 :: の前に配置され、メソッドの名前はその後に提供されます。

例えば:

Computer::getAge;

Computerクラスで定義されているメソッドgetAgeへのメソッド参照を調べています。

次に、その機能を操作できます。

Function<Computer, Integer> getAge = Computer::getAge;
Integer computerAge = getAge.apply(c1);

関数を参照していることに注意してください–そしてそれを正しい種類の引数に適用します。

4. メソッドリファレンス

かなりのシナリオで、この演算子をうまく利用できます。

4.1. 静的メソッド

まず、静的ユーティリティメソッドを利用します。

List inventory = Arrays.asList(
  new Computer( 2015, "white", 35), new Computer(2009, "black", 65));
inventory.forEach(ComputerUtils::repair);

4.2. 既存のオブジェクトのインスタンスメソッド

次に、興味深いシナリオを見てみましょう–既存のオブジェクトインスタンスのメソッドを参照する

変数SystemoutprintメソッドをサポートするタイプPrintStreamのオブジェクトを使用します。

Computer c1 = new Computer(2015, "white");
Computer c2 = new Computer(2009, "black");
Computer c3 = new Computer(2014, "black");
Arrays.asList(c1, c2, c3).forEach(System.out::print);

4.3. 特定のタイプの任意のオブジェクトのインスタンスメソッド

Computer c1 = new Computer(2015, "white", 100);
Computer c2 = new MacbookPro(2009, "black", 100);
List inventory = Arrays.asList(c1, c2);
inventory.forEach(Computer::turnOnPc);

ご覧のとおり、 turnOnPc メソッドは、特定のインスタンスではなく、型自体で参照しています。

4行目では、インスタンスメソッドturnOnPcinventoryのすべてのオブジェクトに対して呼び出されます。

そしてこれは当然、 c1 の場合、メソッド turnOnPcComputerインスタンスで呼び出され、c2の場合はMacbookProで呼び出されることを意味します。 インスタンス。

4.4. 特定のオブジェクトのスーパーメソッド

Computerスーパークラスに次のメソッドがあるとします。

public Double calculateValue(Double initialValue) {
    return initialValue/1.50;
}

これはMacbookProサブクラスにあります:

@Override
public Double calculateValue(Double initialValue){
    Function<Double, Double> function = super::calculateValue;
    Double pcValue = function.apply(initialValue);
    return pcValue + (initialValue/10) ;
}

MacbookProインスタンスでのcalculateValueメソッドの呼び出し:

macbookPro.calculateValue(999.99);

また、ComputerスーパークラスのcalculateValueへの呼び出しも生成します。

5. コンストラクター参照

5.1. 新しいインスタンスを作成する

オブジェクトをインスタンス化するためにコンストラクターを参照することは非常に簡単です。

@FunctionalInterface
public interface InterfaceComputer {
    Computer create();
}

InterfaceComputer c = Computer::new;
Computer computer = c.create();

コンストラクターに2つのパラメーターがある場合はどうなりますか?

BiFunction<Integer, String, Computer> c4Function = Computer::new; 
Computer c4 = c4Function.apply(2013, "white");

パラメータが3つ以上の場合は、新しい機能インターフェイスを定義する必要があります。

@FunctionalInterface 
interface TriFunction<A, B, C, R> { 
    R apply(A a, B b, C c); 
    default <V> TriFunction<A, B, C, V> andThen( Function<? super R, ? extends V> after) { 
        Objects.requireNonNull(after); 
        return (A a, B b, C c) -> after.apply(apply(a, b, c)); 
    } 
}

次に、オブジェクトを初期化します。

TriFunction <Integer, String, Integer, Computer> c6Function = Computer::new;
Computer c3 = c6Function.apply(2008, "black", 90);

5.2. アレイを作成する

最後に、5つの要素を持つComputerオブジェクトの配列を作成する方法を見てみましょう。

Function <Integer, Computer[]> computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);

6. 結論

私たちが見始めているように、Java 8で導入された二重コロン演算子は、いくつかのシナリオで、特にStreamsと組み合わせて非常に役立ちます。

舞台裏で何が起こっているのかをよりよく理解するために、機能的なインターフェースを調べることも非常に重要です。

この例の完全なソースコードは、このGitHubプロジェクトで入手できます。これはMavenおよびEclipseプロジェクトであるため、そのままインポートして使用できます。