Gibt es einen Unterschied zwischen Objects :: nonNull und x -> x! = Null?

Betrachten Sie die folgende Klasse:

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;
    }
}

Das erste Prädikat wird aus einer Methodenreferenz und das andere aus einem Lambda-Ausdruck erstellt. Diese Prädikate haben das gleiche Verhalten (nonNullDer Körper ist gerechtreturn obj != null;). Das Lambda ist zwei Zeichen kürzer (möglicherweise passt eine Stream-Pipeline auf eine Zeile).

Anders als Code-Stil,Gibt es einen Unterschied zwischenObjects::nonNull undx -> x != null? Anders ausgedrückt, sollte ich eine der anderen vorziehen?

Das Lambda-Dev und Lambda-Libs-Spec- {Beobachter, Experten} Mailing-Liste Nachrichten zu erwähnenisNull, nonNull undisNotNull (früher Name) hat diesen Punkt nicht angesprochen. (Ich bin überrascht, dass niemand in Frage gestellt hat, die Objects-Methoden hinzuzufügen, da sie trivial durch ein Lambda ersetzt werden könnenInteger::sum.)

Ich habe mir auch den Bytecode mit angeschautjavap. Der einzige Unterschied bestand darin, dass das Methodenhandle an das übergeben wurdeLambda-Metafactory-Bootstrap-Methode:

  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

Natürlich könnte die Metafactory nach Lust und Laune der JVM verschiedene Aktionen für Methodenreferenzen und Lambdas ausführen, was nicht viel beweist.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage