2017-06-14 11 views
24

Ich traf gerade diesen „Bug“, aber ich bin nicht sicher, ob dies beabsichtigt ist: Code:Warum wird InvokeLater im Haupt-Thread ausgeführt?

public static Object someMethod(){ 
    assert SwingUtilities.isEventDispatchThread(); 
    return new Object(); 
} 

public static void main(String[] args){ 
    SwingUtilities.invokeLater(() -> someMethod().toString());//First Example 
    SwingUtilities.invokeLater(someMethod()::toString);//Second Example 
} 

Im ersten Beispiel someMethod auf dem Schaukel Thread ausgeführt wird, aber im zweiten Beispiel es ist nicht, obwohl es meiner Meinung nach sein sollte.

Ist das ein Fehler oder ist das beabsichtigt?

+4

Es sieht so aus, als ob die Methodenreferenz das richtige Objekt oder die richtige Klasse als erstes Argument benötigt, nicht irgendeine Art, sie zu erhalten, also wird die Methode im Hauptthread aufgerufen, die die Assertion unterbricht. Ohne Assertion würde das Ergebnis der Methode verwendet werden, um 'methodResult :: toString' zu erzeugen, was äquivalent zu'() -> methodResult.toString() 'ist. – Pshemo

+18

Wo ist der Fehler? Im zweiten Aufruf wird 'someMethod()' selbst im 'main'-Körper (also im' main'-Thread) ausgewertet, und dann wird ein Verweis auf die 'toString'-Methode des resultierenden Objekts an 'invokeLater' übergeben '. – RealSkeptic

+4

Siehe auch [Was ist der äquivalente Lambda-Ausdruck für 'System.out :: println'] (https://stackoverflow.com/a/28025717/2711488) ... – Holger

Antwort

62

Für mich scheint es wie ein Missverständnis auf Ihrer Seite

Die erste Zeile ist wie wenn man sagt: „Ok, Swing, was ich Ihnen invokeLater wollen, ist someMethod().toString()“. So Schwingen führt es

Die zweite Zeile ist wie wenn man sagt: „Ok, Swing, was ich will Sie invokeLater ist die Methode toString() des Objekts von der Methode zurück someMethod()“. Eine Methode, die someMethod()ich jetzt

So ist das Ergebnis völlig logisch mir

Denken Sie daran, bin Ausführung, dass, bevor Sie eine Funktion (in diesem Fall invokeLater) Auswertung Java, alle Argumente bewerten muss. So im ersten Fall Java eine Lambda-Funktion (keine Notwendigkeit zur Ausführung es) zu bewerten und im zweiten Fall trifft es auf einen Methodenaufruf so muss es ausführt es

+0

Die Frage ist dann: Warum erlaubt Java keine Aussagen wie 'SwingUtilities.invokeLater (this :: someMethod(). ToString);'? – RoiEX

+11

Sie machen dort einige Fehler. Beachten Sie, dass Sie 'this' nicht in einem statischen Kontext verwenden können. Auch wenn Sie eine Methodenreferenz verwenden, fügen Sie nicht das '()' nach dem Methodennamen ein (es wäre also 'this :: someMethod'). Schließlich erlaubt Java 8 Methodenreferenz, aber was Sie versuchen zu verwenden, ruft eine Methode für das Objekt auf, die aus einer Methodenreferenz resultiert (was nicht erlaubt ist) – Pelocho

+7

Zusammenfassend, wenn Sie mehr als eine Methode aufrufen müssen, benötigen Sie a Lambda-Funktion – Pelocho

8

Dies ist nicht im Zusammenhang mit Schaukel, dann ist es das, was passiert, wenn Methodenreferenzen und Lambdas hinter den Kulissen verwendet werden.

Ein einfacheres Beispiel:

public static void main(String[] args) { 
    Stream.of(1, 2, 3).map(initMapper()::inc); 

    Stream.of(1, 2, 3).map(x -> initMapper().inc(x)); 
} 

private static Mapper initMapper() { 
    System.out.println("init"); 
    return new Mapper(); 
} 

static class Mapper { 

    public int inc(int x) { 
     return x + 1; 
    } 
} 

Sie werden hier einzelne init Ausgabe erhalten; Beachten Sie, dass es für den Stream keine Terminaloperation gibt.

Verwandte Themen