1. ホーム
  2. java

[解決済み] :: (ダブルコロン) 演算子 in Java 8

2022-03-20 16:15:58

質問

を探っていました。 Java 8 のソースで、このコードの特定の部分が非常に驚くべきものであることを発見しました。

//defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
    return evaluate(ReduceOps.makeInt(op));
}

@Override
public final OptionalInt max() {
    return reduce(Math::max); //this is the gotcha line
}

//defined in Math.java
public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

Math::max メソッドポインタのようなものでしょうか? 通常の static メソッドに変換されます。 IntBinaryOperator ?

解決方法は?

通常であれば reduce メソッドを使用しています。 Math.max(int, int) を以下のように設定します。

reduce(new IntBinaryOperator() {
    int applyAsInt(int left, int right) {
        return Math.max(left, right);
    }
});

を呼び出すだけで、多くの構文が必要になります。 Math.max . そこで登場するのがラムダ式です。Java 8以降では、同じことをもっと短い方法で行うことができるようになりました。

reduce((int left, int right) -> Math.max(left, right));

これはどのように機能するのでしょうか?Javaコンパイラは、あなたが2つの int を返し、1つの int . これは、インターフェイスの唯一無二のメソッドの正式なパラメータと同等です IntBinaryOperator (メソッドのパラメータ reduce を呼び出したい)。つまり、コンパイラはあなたのために残りを行います。 IntBinaryOperator .

しかし Math.max(int, int) の形式的な要件を満たしています。 IntBinaryOperator であれば、直接使用することができます。Java 7には、メソッド自体を引数として渡すことができる構文がないため(メソッドの結果のみを渡すことができ、メソッドの参照は決して渡すことができません)、メソッドを直接使用することはできません。 :: の構文は、メソッドを参照するためにJava 8で導入されました。

reduce(Math::max);

これは、実行時にJVMが解釈するのではなく、コンパイラが解釈することに注意してください! 3つのコード・スニペットすべてについて異なるバイトコードを生成しますが、意味的には等しいので、最後の2つは、短い(そしておそらくより効率的な)バージョンの IntBinaryOperator を実装しました。

(参照 ラムダ式の翻訳 )