2017-06-14 18 views
24

は、私はこの「バグ」に遭遇するが、私はこれが意図されている場合はわからない: コード:最初の例someMethodinvokeLaterがメインスレッドで実行されるのはなぜですか?

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 
} 

スイングスレッド上で実行されているが、2番目の例では、それ私の意見ではありますが、そうではありません。

これはバグですか?そうですか? 「OK、スイングは、私はinvokeLaterにあなたを望むものsomeMethod().toString()です」:

+4

メソッドリファレンスは、最初の引数として適切なオブジェクトまたはクラスを必要とするように見えますが、メソッドを取得するための方法ではないため、主スレッドでアサーションを中断するメソッドが呼び出されます。 '' methodResult.toString() ''と同等の 'methodResult :: toString'を作成するために、メソッドのアサーション結果を使用しないでください。 – Pshemo

+18

バグはどこですか? 2番目の呼び出しで 'someMethod()'自体が 'main'本体で評価され(' main'スレッドで)、結果オブジェクトの 'toString'メソッドへの参照が' invokeLater '。 – RealSkeptic

+4

も参照してください。[System.out :: println'の同等のラムダ式は何ですか?](https://stackoverflow.com/a/28025717/2711488)... – Holger

答えて

62

は、私にはそれが最初の行が言うようなものですあなたの側

上の誤解のように思えます。だからスウィングはそれを実行します

2行目は次のように言います:invokeLaterには、someMethod()というメソッドで返されたオブジェクトのメソッドtoString()があります。私は今

を実行していますsomeMethod()方法は、その結果は

だけ(この場合はinvokeLaterで)機能を評価する前に、Javaはすべての引数を評価する必要があることに注意してください私には完全に論理的です。だから、最初のケースでは、Javaがラムダ関数(それを実行する必要はありません)を評価し、後者の場合には、それはメソッド呼び出しに遭遇したので、それはそれをこのスイングに関連ないある

+0

質問は次のとおりです。 'SwingUtilities.invokeLater(this :: someMethod()。toString);'? – RoiEX

+11

あなたはいくつかの間違いを犯しています。静的コンテキストでは 'this'を使用できないことに注意してください。また、メソッド参照を使用している場合は、メソッド名の後ろに '()'を置かないでください( 'this :: someMethod'となります)。最後に、Java 8ではメソッド参照が許可されていますが、メソッド参照の結果であるオブジェクトのメソッドを呼び出すことは許可されていません。 – Pelocho

+7

要約すると、複数のメソッドを呼び出す必要がある場合は、ラムダ関数 – Pelocho

8

を実行する必要がある、それは何ですか舞台裏でメソッド参照とラムダを使用すると発生します。

シンプルな例:

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

あなたがここに単一init出力が得られます。ストリームのターミナル操作がないことに注意してください。

関連する問題