为什么invokeLater在主线程中执行?

时间:2017-06-14 11:26:59

标签: java multithreading lambda java-8 method-reference

我刚遇到这个“bug”,但我不确定这是不是意图: 代码:

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正在执行swing线程,但在第二个示例中它不是,虽然它应该在我看来。

这是一个错误还是这个?

2 个答案:

答案 0 :(得分:62)

对我而言,这似乎是对你的误解

第一行就像是说:"好的,Swing,我想要你invokeLater someMethod().toString()"。所以Swing执行它

第二行就像是说:"好的,Swing,我想要你invokeLater的方法是方法toString()&#返回的对象的方法someMethod() 34 ;.一种someMethod()方法我现在正在执行

所以结果对我来说完全符合逻辑

请记住,在评估函数之前(在本例中为invokeLater),Java需要评估所有参数。因此,在第一种情况下,Java评估lambda函数(不需要执行它),在第二种情况下,它遇到方法调用所以它需要执行它

答案 1 :(得分:8)

与Swing有关,这是在幕后使用方法引用和lambdas时会发生的事情。

一个更简单的例子:

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输出;注意流没有终端操作。