次のクラスを検討してください。
import java.util.Objects;
import java.util.function.Predicate;
public class LambdaVsMethodRef {
public static void main(String[] args) {
Predicate<Object> a = Objects::nonNull;
Predicate<Object> b = x -> x != null;
}
}
最初の述語はメソッド参照から作成され、もう 1 つはラムダ式から作成されます。これらの述語は同じ振る舞いをします (nonNull
の本体はただ ですreturn obj != null;
)。ラムダは 2 文字短くなります (おそらく、ストリーム パイプラインを 1 行に収めることができます)。
コード スタイル以外に、 と の間に違いはObjects::nonNull
ありx -> x != null
ますか? 別の言い方をすれば、どちらかを優先する必要がありますか?
lambda-dev と lambda-libs-spec-{observers,experts} のメーリング リスト メッセージではisNull
、nonNull
とisNotNull
(初期の名前) に言及していましたが、この点については触れられていませんでした。(Objects メソッドをラムダで簡単に置き換えることができるので、誰も疑問を呈していないことに驚いていますが、一方で、そうですInteger::sum
。)
でバイトコードも見ましたjavap
。唯一の違いは、ラムダ メタファクトリ ブートストラップ メソッドに渡されるメソッド ハンドルです。
BootstrapMethods:
0: #16 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#17 (Ljava/lang/Object;)Z
#18 invokestatic java/util/Objects.nonNull:(Ljava/lang/Object;)Z
#17 (Ljava/lang/Object;)Z
1: #16 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#17 (Ljava/lang/Object;)Z
#20 invokestatic LambdaVsMethodRef.lambda$main$1:(Ljava/lang/Object;)Z
#17 (Ljava/lang/Object;)Z
もちろん、メタファクトリーは JVM の気まぐれで、メソッド参照とラムダに対して異なることを行うことができるので、あまり証明されません。