首页 > 解决方案 > 为什么我们不能直接在 Lambda 函数中调用 Thread#sleep()?

问题描述

下面的代码给了我一个编译时错误:

Thread t2 = new Thread(() -> {
    try { 
        sleep(1000);
    } 
    catch (InterruptedException e) {}
});

对于类型 A (其中 A 是我的类名),方法 sleep(int) 是未定义的。

然而,当我使用匿名内部类时,没有编译时错误:

Thread t1 = new Thread(){
    public void run(){
        try {
            sleep(1000);
        } catch (InterruptedException e) {}
    }
};

下面的代码也可以正常工作:

Thread t3 = new Thread(() -> System.out.println("In lambda"));

在 lambda 表达式主体中是如何工作的?请帮忙。

从许多答案中,我可以看到可以使用Thread.sleep(1000)我的第一种方法解决该错误。但是,如果有人能向我解释作用域和上下文如何在 lambda 表达式中工作,我将不胜感激。

标签: javamultithreadinglambdajava-8

解决方案


Thread.sleepThread类中的静态方法。

sleep您可以在匿名类中直接调用而无需任何限定符的原因是因为您实际上处于继承自Thread. 因此,sleep在那里可以访问。

但是在 lambda 的情况下,你不在一个继承自Thread. 您在围绕该代码的任何类中。因此,sleep不能直接调用,需要说Thread.sleep. 该文档也支持这一点:

Lambda 表达式是词法范围的。这意味着它们不会从超类型继承任何名称或引入新级别的范围。lambda 表达式中的声明被解释为它们在封闭环境中的样子。

基本上这就是说,在 lambda 内部,您实际上处于与 lambda 外部相同的范围内。如果你不能sleep在 lambda 之外访问,你也不能在里面。

另外,请注意,您在此处显示的两种创建线程的方法本质上是不同的。在 lambda 中,您将 a 传递RunnableThread构造函数,而在匿名类中,您Thread通过直接创建它的匿名类来创建 a。


推荐阅读