Java 8の二重コロン演算子

Java 8の二重コロン演算子

1. 概要

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

参考文献:

Java 8インタビューの質問(回答)

よくあるJava8関連のインタビューの質問ともちろん回答のセット。

Java 8オプションガイド

Java 8のOptionalへの迅速かつ実用的なガイド

Java 8の新機能

Java 8の新機能の簡単な紹介。焦点は、デフォルトおよび静的インターフェイスメソッド、静的メソッド参照、およびオプションです。

2. ラムダスからダブルコロンオペレーターへ

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

たとえば、create a comparatorの場合、次の構文で十分です。

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 getAge = Computer::getAge;
Integer computerAge = getAge.apply(c1);

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

4. メソッド参照

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

4.1. 静的メソッド

まず、a static utility methodを利用します。

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

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

次に、興味深いシナリオであるreferencing a method of an existing object instanceを見てみましょう。

変数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 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 c4Function = Computer::new;
Computer c4 = c4Function.apply(2013, "white");

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

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

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

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

5.2. 配列を作成する

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

Function  computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);

6. 結論

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

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

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