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 (nonNull
Der 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.