2017-06-14 30 views
24

我只是遇到了这个“错误”,但我不知道这是否意: 代码:为什么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正在对Swing线程执行,但在第二个例子中它不是,虽然它应该在我看来。

这是一个错误还是这是打算?

+4

它看起来像方法引用需要适当的对象或类作为第一个参数,而不是某种方式来获取它,所以方法在主线程中调用,断言断言。没有声明方法的结果将被用于创建'methodResult :: toString',这相当于'() - > methodResult.toString()'。 – Pshemo

+18

错误在哪里?在第二次调用中,'someMethod()'本身在'main'主体(因此在'main'线程)中被计算,然后,对结果对象的'toString'方法的引用被传递给'invokeLater '。 – RealSkeptic

+4

另请参见[什么是'System.out :: println'的等效lambda表达式](https://stackoverflow.com/a/28025717/2711488)... – Holger

回答

62

对我来说,好像就在你身边

一个误会第一行就像是说:“好好好,秋千,我要你invokeLatersomeMethod().toString()”。所以Swing执行它

第二行就像是说:“好的,Swing,我想要你invokeLater是方法someMethod()返回的对象的方法toString()”。一个someMethod()方法我执行现在

所以结果是完全合乎逻辑的我

只要记住,在评价函数(在这种情况下invokeLater)之前,Java需要评估所有参数。因此,在第一种情况下的Java评估lambda函数(无需执行它),在第二种情况下它遇到一个方法调用所以它需要执行它

+0

问题是:为什么不允许像这样的语句'SwingUtilities.invokeLater(这::的someMethod()的toString);'? – RoiEX

+11

你在那里犯了几个错误。注意你不能在静态的环境中使用'this'。另外,如果您使用方法引用,则不要在方法名称之后放置'()'(所以它会是'this :: someMethod')。最后,Java 8允许方法引用,但是你试图使用的方法是调用一个方法引用的方法(这是不允许的) – Pelocho

+7

总结,如果你需要调用多个方法,你需要一个方法lambda函数 – Pelocho

8

这是到Swing相关的,它是什么在幕后使用方法引用和lambda时会发生。

一个简单的例子:

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

相关问题