为什么我们不能直接在 Lambda 函数中调用 Thread#sleep()?

2022-08-31 16:19:50

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

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

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

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

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

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

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

在 lambda 表达式正文中,事情是如何运作的?请帮忙。

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


答案 1

Thread.sleep是类中的静态方法。Thread

在匿名类中,无需任何限定符即可直接调用的原因是,您实际上处于从 继承的类的上下文中。因此,可以在那里访问。sleepThreadsleep

但在 lambda 的情况下,您不在继承自 的类中。您位于围绕该代码的任何类中。因此,不能直接调用,您需要说.文档还支持以下内容:ThreadsleepThread.sleep

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

基本上,这是在lambda内部,您实际上处于与lambda之外相同的范围内。如果您无法在 lambda 外部访问,则也无法在内部访问。sleep

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


答案 2

在第一种方法中,您将 a 传递给 ,您需要调用 :RunnableThreadThread.sleep

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

它是以下的简短版本:

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

Thread t2 = new Thread(runnable);

在第二个中,您直接重写了方法,因此可以调用 。thread.runthread.sleepthread.run


推荐