Why does invokeLater execute in the main thread?

2020-05-21 18:53发布

I just encountered this "bug", but I'm not sure if this is intended: Code:

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
}

In the first example someMethod is being executed on the swing Thread, but in the second example it is not, although it should be in my opinion.

Is this a bug or is this intended?

2条回答
Summer. ? 凉城
2楼-- · 2020-05-21 19:07

To me it seems like a misunderstanding on your side

The first line is like saying: "Ok, Swing, what I want you to invokeLater is someMethod().toString()". So Swing executes it

The second line is like saying: "Ok, Swing, what I want you to invokeLater is the method toString() of the object returned by the method someMethod()". A someMethod() method that I am executing right now

So the result is completely logical to me

Just keep in mind that before evaluating a function (in this case invokeLater) Java needs to evaluate all arguments. So in the first case Java evaluate a lambda function (no need to execute it) and in the second case it encounters a method invocation so it needs to execute it

查看更多
戒情不戒烟
3楼-- · 2020-05-21 19:18

This is not related to Swing, it's what happens when using method references and lambdas behind the scenes.

A simpler example:

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

You will get a single init output here; notice that there is no terminal operation for the stream.

查看更多
登录 后发表回答