2016-12-30 4 views
3

Ich würde erwartet, dass beide Put-Operationen eine NullPointerException in den folgenden Code werfen, aber tatsächlich funktioniert der Lambda-Ausdruck gut, während nur die Methodenreferenz eine NPE auslöst.Unterschied zwischen Methodenreferenz und Lambda

public static void main(String... args) { 
    Object object = null; 
    Map<String, FuncInterface> map = new HashMap<>(); 

    map.put("key1",() -> object.notify()); // works 
    map.put("key2", object::notify);   // throws NPE 
} 

@FunctionalInterface 
private interface FuncInterface { 
    public void someAction(); 
} 

Was ist der Unterschied?

+0

Ich habe auch versucht, Ihren Code, aber immer NPE für beide Fälle. –

+0

@SunilSinghBora verwenden Sie Eclipse? – assylias

+0

Ja. Ich führe diesen Code in Eclipse IDE. –

Antwort

6

Das Lambda wird ausgewertet, wenn es aufgerufen wird: Wenn Sie map.get("key1").someAction() aufgerufen haben, erhalten Sie eine NPE.

Die Methodenreferenz wird zur Erstellungszeit ausgewertet, d. H. Wenn Sie zum ersten Mal object::notify schreiben, was eine NPE sofort auslöst.

Insbesondere the JLS 15.13.3 Zustände:

Auswertung eines Expressionsverfahren Referenz von Aufruf der Methode selbst verschieden.
Wenn der Methodenreferenzausdruck mit einem Ausdrucksnamen oder einem Primärwert beginnt, wird dieser Teilausdruck ausgewertet. Wenn der Teilausdruck null ergibt, wird eine NullPointerException ausgelöst, und der Methodenreferenzausdruck wird abrupt beendet.

+0

Bitte entschuldigen Sie einen .net-Entwickler, der nur gelegentlich nach Java umleitet, aber da das Objekt nicht als endgültig markiert ist, welche Regel (n) das Kompilieren erlaubt (aber sich beschweren, wenn Sie tatsächlich ein Objekt erneut zuweisen, tut _not_ jammern über die Nullreferenz, wenn Sie keine Instanz zum finalen Object-Objekt zuweisen) ;-) edit: oh, muss etwas über "effektiv final" sein; Vergiss es. – VolkerK

+0

Ich bin mir nicht sicher, ob ich Ihre Frage vollständig verstanden habe, aber der Compiler führt keine Nullprüfungen durch. Sie können 'Objekt o = null; o.toString(); 'wenn Sie möchten: es wird kompiliert. – assylias

+0

Wenn Sie 'Object object = null 'in' Object object = new Object() 'ändern, wird der Compiler über das Objekt, das im Lambda nicht endgültig ist, beschweren. Auf der anderen Seite, wenn Sie es als final markieren, aber es "null" behalten, beschwert sich der Compiler nicht über "object :: notify", d. H. Null :: notify. Aber ja, ich habe erst nach dem Posten meiner "Frage" bemerkt, dass der Compiler nach "effektiv final" gesucht hat, also ist das Verhalten nicht so inkonsistent wie ich zuerst dachte. – VolkerK

Verwandte Themen