web-dev-qa-db-ja.com

なぜinvokeLaterがメインスレッドで実行されるのですか?

この「バグ」に遭遇したばかりですが、これが意図されているかどうかはわかりません。コード:

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
}

最初の例では、someMethodはswingThreadで実行されていますが、2番目の例では実行されていませんが、私の意見ではそうです。

これはバグですか、それとも意図されたものですか?

24
RoiEX

私にはそれはあなたの側の誤解のように思えます

最初の行は、「OK、Swing、invokeLaterにしてほしいのはsomeMethod().toString()です」と言っているようなものです。だからSwingはそれを実行します

2行目は、「OK、Swing、invokeLaterにしてほしいのは、メソッドtoString()によって返されるオブジェクトのメソッドsomeMethod()です」と言っているようなものです。 someMethod()メソッド私は今実行しています

したがって、結果は私にとって完全に論理的です

関数(この場合はinvokeLater)を評価する前に、Javaはすべての引数を評価する必要があることを覚えておいてください。したがって、最初の場合はJava =ラムダ関数を評価し(実行する必要はありません)、2番目のケースではメソッド呼び出しに遭遇します実行する必要があります

61
Pelocho

これはnot Swingに関連しており、メソッド参照とラムダを舞台裏で使用するとどうなりますか。

より簡単な例:

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出力が得られます。ストリームのターミナル操作がないことに注意してください。

8
Eugene