首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么可以在Thread类中使用Lambda表达式?

为什么可以在Thread类中使用Lambda表达式?
EN

Stack Overflow用户
提问于 2014-07-20 03:21:00
回答 2查看 3.9K关注 0票数 5

我正在学习Lambda表达式,我知道可以在运行函数接口和线程类中使用它们。

我试着创造自己的:

代码语言:javascript
运行
复制
package tests;

public interface Blabla
{
    public void doStuff();
}

这个简单的测试被编译成:

代码语言:javascript
运行
复制
Blabla bla = () -> System.out.println("Lol");

然后我试着做一个像Thread这样的类

代码语言:javascript
运行
复制
package tests;

public class Dodo implements Blabla
{
    public void doStuff()
    {
        // TODO Auto-generated method stub

    }
}

而这并没有编译:

代码语言:javascript
运行
复制
 Dodo dodo = () -> System.out.println("LoL");

我找不到任何地方解释如何创建一个允许使用lambda表达式的类。

线程如何允许使用Lambda表达式而不是接口?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-20 04:46:38

线程如何允许使用Lambda表达式而不是接口?

我想您对Thread类如何使用lambdas感到有点困惑。lambdas不被转换为Thread类本身的实例;相反,lambdas被转换为子类Runnable functional的实例,然后将其传递给一个线程构造函数,该构造函数已经是重载以获取可运行的对象

因此,当您这样做时:

代码语言:javascript
运行
复制
new Thread(() -> System.out.println("Lol")).start();

lambda没有转换为正在创建的Thread对象。相反,它被转换为传递给线程构造函数的Runnable对象。

如果您将lambda从Thread对象中分离出来,这就更清楚了:

代码语言:javascript
运行
复制
Runnable temp = () -> System.out.println("Lol");

new Thread(temp).start();

它可能有助于认为线程执行一个函数,而不是一个函数。您必须保持线程正在执行的函数与线程本身不同。

请注意,将lambda转换为对象的方式是一个实现细节,并且在未来的Java中可能会发生变化(Java是编写此答案时的最新版本)。见下面斯图尔特·马克斯的评论。

我找不到任何地方解释如何创建一个允许使用lambda表达式的类。

如果我对您的理解是正确的,您希望编写一个类,这样就可以基于该类创建lambda。

不幸的是,你不能。看看Java语言规范,第15.27节:

对lambda表达式的评估会产生一个功能接口的实例(§9.8)。

这里的关键是lambda是接口的一个实例。因此,不能使用lambda直接子类类。在JDK lambda-dev邮件列表中,Brian的电子邮件中可以找到这样做的理由(感谢Stuart指出了这一点!)。简而言之,这个决定至少部分地是为了让Java能够继续向新的方向发展。

您可以编写一个类,其构造函数和/或方法以一个或多个函数接口作为参数,通过传递函数接口的实例(如Thread类),允许您在lambdas中使用该类。目前(据我所知),这几乎是最好的。

票数 6
EN

Stack Overflow用户

发布于 2017-11-17 08:55:20

lambda表达式只是编写匿名类的一个简短形式,通过使用lambda表达式,我们可以在不需要任何名称的地方声明方法。

编写匿名类对象的唯一目的是覆盖它的方法并提供我们自己的功能,但是对于这个方法,我们总是需要声明类。使用lambda表达式,我们可以消除匿名类的声明,只需提供方法的定义。

例如,我们使用下面的代码创建一个线程

代码语言:javascript
运行
复制
Runnable runnable = new Runnable() {
  @Override
  public void run() {
  System.out.println("Running thread using anonymous class");
  }
};
Thread t = new Thread(runnable);

但是使用lambda表达式,我们可以很容易地说

代码语言:javascript
运行
复制
Runnable runnable = () -> System.out.println("Running thread using lambda expression");
Thread t = new Thread(runnable);

代码语言:javascript
运行
复制
Thread t = new Thread(() -> System.out.println("Running thread using lambda expression"));

因此,通过编写Runnable runnable = () -> System.out.println("Running thread using lambda expression");,我们告诉Java创建一个类型为Runnable的匿名对象,并为run()方法提供了主体。

Lambda表达式只在functional interfaces (其中只有一个方法的接口)上工作,因为我们正在动态地为该方法提供主体。因此,如果一个接口有多个方法,并且允许我们在它上创建lambda,那么编译器将如何识别这个提供的方法主体属于哪个方法。

Lambda表达式与匿名类的区别如下

  • 一个匿名类对象在编译后创建一个单独的类文件,这增加了jar的大小,而在编译之后,Lambda表达式变成了动态语言实现的invokedynamic。
  • 我们可以使用这个关键字来表示lambda表达式中的当前类,而对于匿名类,这个关键字表示特定的匿名类。
  • 对于Lambda表达式,我们只需要提供函数体,而对于匿名类,则需要编写冗余类定义。

您可以在用示例说明Java表达式上阅读更多内容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24847032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档