Lambda Ausdrücke: @FunctionalInterface Instanzen auf null prüfen

Sasa

Mitglied
Hallo,

kann ich in Java 8 prüfen, ob eine @FunctionalInterface Instanz von einem null Object kommt?

Das Problem ist, wenn ich so eine Instanz habe, tritt eine java.lang.NullPointerException auf, wenn ich deren Funktion aufrufe:
Java:
@Test
public void testNullObjectMethod() {
    Collection<?> collection = null;
    Predicate<Collection<?>> predicate = collection::equals;
    Assert.assertNotNull(predicate); // OK
    Assert.assertTrue(predicate instanceof Predicate<?>); // OK
    predicate.test(Collections.EMPTY_LIST); // NPE
}
 

Ruzmanz

Top Contributor
Ich bin da noch selbst ein Neuling ... sofern ich das richtig Verstanden habe, muss man in diesen Fällen die Klasse "Optional" nutzen.
 

nvidia

Bekanntes Mitglied
Ich bin da noch selbst ein Neuling ... sofern ich das richtig Verstanden habe, muss man in diesen Fällen die Klasse "Optional" nutzen.

Was er versucht ist einfach eine "Methodenreferenz" von einem Objekt zu erhalten das nicht existiert. Die NPE fliegt nicht dort wo er sie markiert hat, sondern schon in der Zeile in der er versucht sich die Methodenreferenz von einer Null-Referenz zu organisieren. Auch Optional wird da nicht helfen, stopfst du da null rein und versuchst den Wert zu holen (die Collection) fliegt genauso eine Exception aber dieses mal wirft Optional die.
 

Sasa

Mitglied
Was er versucht ist einfach eine "Methodenreferenz" von einem Objekt zu erhalten das nicht existiert. Die NPE fliegt nicht dort wo er sie markiert hat, sondern schon in der Zeile in der er versucht sich die Methodenreferenz von einer Null-Referenz zu organisieren. Auch Optional wird da nicht helfen, stopfst du da null rein und versuchst den Wert zu holen (die Collection) fliegt genauso eine Exception aber dieses mal wirft Optional die.
Meine ursprüngliche Erwartung war auch, dass ich die Exception in Zeile 4. bekomme (Für das Beispiel zeigt Eclipse dort auch eine Warnung an "Null pointer access: The variable collection can only be null at this location").

Aber die Ausführung geht weiter - die Assertions in Zeile 5. und 6. werden erfolgreich durchlaufen! Die Exception fliegt tatsächlich erst in Zeile 7.
 

nvidia

Bekanntes Mitglied
[...]Die Exception fliegt tatsächlich erst in Zeile 7.

Ok, lass es mich so formulieren. Es gibt Eclipse und es gibt die Realität. Eclipse verwendet standardmäßig seinen eigenen Compiler um *.class Dateien zu erzeugen. Deren Bytecode muss nicht mit dem übereinstimmen was der javac ausspuckt der bei einem JDK mit dabei ist. Und genau auf dieses Problem bist du gestoßen.

Wird der folgende Code über die Kommandozeile mit den JDK-Werkzeugen kompiliert.
Java:
import java.util.Collection;
import java.util.Collections;
import java.util.function.Predicate;

import org.junit.Assert;
import org.junit.Test;

public class methodrefTest {
    @Test
    public void myMethod(){
    	Collection<?> collection = null;
        Predicate<Collection<?>> predicate = collection::equals;
        Assert.assertNotNull(predicate); // OK
        Assert.assertTrue(predicate instanceof Predicate<?>); // OK
        predicate.test(Collections.EMPTY_LIST); // NPE
    }
}

Dann erhält man bei Ausführung über die Kommandozeile folgendes Ergebnis, das deutlich zeigt das die Exception genau dort fliegt wo man sie auch erwarten würde.

java.lang.NullPointerException
at methodrefTest.myMethod(methodrefTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runners.Suite.runChild(Suite.java:127)
at org.junit.runners.Suite.runChild(Suite.java:26)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at org.junit.runner.JUnitCore.run(JUnitCore.java:138)
at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:96)
at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:47)
at org.junit.runner.JUnitCore.main(JUnitCore.java:40)

Ich bemerkte das nicht sofort, weil ich IntelliJ nutze. IntelliJ verwendet standardmäßig den javac des eingestellten JDK.
 
Zuletzt bearbeitet:

Sasa

Mitglied
@nvidia: OK, du hast recht. Das war ein Problem von Eclipse - übrigens Version="Luna M7 Release (4.4.0M7)" (Ich hoffe, dass sie das bis zum finalen Release beheben...)
 

Natac

Bekanntes Mitglied
@nvidia: OK, du hast recht. Das war ein Problem von Eclipse - übrigens Version="Luna M7 Release (4.4.0M7)" (Ich hoffe, dass sie das bis zum finalen Release beheben...)
Macht es Eclipse aber nicht eigentlich richtig, da
Code:
collection::equals
doch eine statische Methoden-Referenz ist, also identisch mit [c]Collection::equals[/c]?

Zum nachdenken (aus einem anderen Forum):
Java:
public class FluentCallTest
{
    public static void main(String[] args)
    {
        das().funktioniert().nicht();
    }    
    static FluentCallTest das()
    {
        System.err.print("das ");
        return null;
    }
    static FluentCallTest funktioniert()
    {
        System.err.print("funktioniert ");
        return null;
    }
    FluentCallTest nicht()
    {
        System.err.println("nicht");
        return null;
    }
}
Ergibt "das funktioniert" und dann eine NPE. Weil funktioniert() static ist, ist der Rückgabewert von das() egal.
 
Zuletzt bearbeitet:

nvidia

Bekanntes Mitglied
Macht es Eclipse aber nicht eigentlich richtig, da
Code:
collection::equals
doch eine statische Methoden-Referenz ist, also identisch mit [c]Collection::equals[/c]?

Nein, in dem Kontext ist es keine statische Methodenreferenz. Es wird versucht eine Methodenreferenz von einem "Objekt" (collection) zu holen welches zufälligerweise null ist. Und zu deinem Beispiel, das war doch schon immer so und hat auch nichts mit den neuen Lambdaausdrücken zu tun.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
A Lambda-Ausdrücke Allgemeine Java-Themen 5
Neumi5694 Lambda - Block vs "Anweisungsliste" Allgemeine Java-Themen 8
R Lambda Expression in einer Methode execute() aufrufen (execute() ist eine Methode aus dem funktionalen Interface Command) Allgemeine Java-Themen 5
LimDul Hä? Lambda-Ausdruck geht, Methoden-Referenz nicht Allgemeine Java-Themen 8
A Lambda und Streams verstehen Allgemeine Java-Themen 4
O Best Practice Lambda Expressions Allgemeine Java-Themen 3
Rudolf Compiler-Fehler Lambda als Argument kompiliert nicht Allgemeine Java-Themen 2
E Lambda filter performance Allgemeine Java-Themen 2
H Collector Generics Problem (incl. Stream & Lambda) Allgemeine Java-Themen 4
M Lambda "invalid method reference no suitable method found" Allgemeine Java-Themen 2
H Consumer (Java8 Lambda) an Timer übergeben Allgemeine Java-Themen 2
J Namen von Methoden über Reguläre Ausdrücke bearbeiten Allgemeine Java-Themen 6
E Reguläre Ausdrücke: String-Ersetzung Allgemeine Java-Themen 0
M Lambada Ausdrücke - wie funktionieren und benutzt man sie? Allgemeine Java-Themen 5
G Reguläre Ausdrücke Allgemeine Java-Themen 11
Z Design um boolsche ausdrücke zu speichern & auszuwerten Allgemeine Java-Themen 3
G Reguläre Ausdrücke Allgemeine Java-Themen 2
S Reguläre Ausdrücke: Polynomterme Allgemeine Java-Themen 14
jstei001 Reguläre Ausdrücke bearbeiten/ändern Allgemeine Java-Themen 14
R Logische Ausdrücke in Java Allgemeine Java-Themen 4
C reguläre Ausdrücke finden nicht was sie finden sollen Allgemeine Java-Themen 8
Loyd Noch ne Regex-Frage: Verschachtelte Ausdrücke Allgemeine Java-Themen 4
H Geklammerte Ausdrücke nach Divide&Conquer Allgemeine Java-Themen 2
F Reguläre Ausdrücke und BBCode Allgemeine Java-Themen 10
J String für reguläre Ausdrücke escapen Allgemeine Java-Themen 2
C Reguläre Ausdrücke - X{0}?.* Allgemeine Java-Themen 8
B Parser für logische Ausdrücke Allgemeine Java-Themen 9
C Reguläre Ausdrücke, String rückwärts durchsuchen Allgemeine Java-Themen 6
J Expression Language für mathematische Ausdrücke Allgemeine Java-Themen 8
B Regeuläre Ausdrücke Allgemeine Java-Themen 8
I Reguläre Ausdrücke und das "~" Symbol Allgemeine Java-Themen 2
G arithmetische ausdrücke Allgemeine Java-Themen 5
B Reguläre ausdrücke mit variablen? Allgemeine Java-Themen 12
H Regex - Reguläre Ausdrücke Allgemeine Java-Themen 3
A Reguläre Ausdrücke vereinfachen Allgemeine Java-Themen 19
J Reguläre Ausdrücke Allgemeine Java-Themen 14
A Zufallswerte für reguläre Ausdrücke Allgemeine Java-Themen 15
G Reguläre Ausdrücke Allgemeine Java-Themen 8
R reguläre Ausdrücke Allgemeine Java-Themen 2
L Reguläre Ausdrücke und Fehlerbehandlung Allgemeine Java-Themen 10
RaoulDuke Reguläre Ausdrücke - Daten extrahieren Allgemeine Java-Themen 3
L reguläre Ausdrücke? Allgemeine Java-Themen 2
R Reguläre Ausdrücke (mehrzeilig) Allgemeine Java-Themen 2
M Regular Expression - verschiedene Ausdrücke testen (grep | ) Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben