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

Xky*_*nar 5 lambda java-8

我正在学习Lambda表达式,我知道可以在Runnable功能界面和Thread类中使用它们.

我试图创建自己的:

package tests;

public interface Blabla
{
    public void doStuff();
}
Run Code Online (Sandbox Code Playgroud)

这个简单的测试编译:

Blabla bla = () -> System.out.println("Lol");
Run Code Online (Sandbox Code Playgroud)

然后我尝试创建一个像Thread这样的类

package tests;

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

    }
}
Run Code Online (Sandbox Code Playgroud)

这不编译:

 Dodo dodo = () -> System.out.println("LoL");
Run Code Online (Sandbox Code Playgroud)

我无法解释如何创建一个允许使用lambda表达式的类.

Thread如何允许在不作为接口的情况下使用Lambda表达式?

awk*_*ksp 5

Thread如何允许在不作为接口的情况下使用Lambda表达式?

我觉得你对Thread类如何使用lambdas感到有点困惑.lambda不会转换为Thread类本身的实例; 相反,lambdas被转换为Runnable功能接口的子类的实例,然后将其传递给已经重载以获取Runnable对象的Thread构造函数.

因此,当你做这样的事情时:

new Thread(() -> System.out.println("Lol")).start();
Run Code Online (Sandbox Code Playgroud)

lambda未转换为您正在创建的Thread对象.相反,它被转换为传递给Thread构造函数的Runnable对象.

如果将lambda与Thread对象分开,则更清楚:

Runnable temp = () -> System.out.println("Lol");

new Thread(temp).start();
Run Code Online (Sandbox Code Playgroud)

它可以帮助想一个线程的执行函数,而不是作为一个功能.您必须保持Thread执行的功能与Thread本身不同.

请注意,lambdas转换为对象的方式是一个实现细节,在将来的Java版本中可能会有所变化(Java 1.8.0_11是编写本答案时的最新版本).请参阅下面的Stuart Marks的评论.


我无法解释如何创建一个允许使用lambda表达式的类.

如果我正确理解你,你希望编写一个类,以便你可以根据该类创建一个lambda.

不幸的是,你做不到.看一下Java语言规范,第15.27节:

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

这里的关键点是lambda是接口的一个实例.因此,您不能使用lambda直接对类进行子类化.这样做的原因可以发现这个电子邮件Brian Goetz撰写的JDK的λ-dev邮件列表(感谢司徒标记指出这一点!); 简而言之,该决定至少部分地做出,因此Java可以继续朝着新的方向发展.

可以做的是编写一个类,其构造函数和/或方法将一个或多个函数接口作为参数,让你通过传递函数接口的实例(如Thread类)来使用lambdas类.目前(据我所知),这非常好.

  • @Xkynar&user3580294:禁止lambdas实现抽象类的基本原理由[来自Brian Goetz的电子邮件](http://mail.openjdk.java.net/pipermail/lambda-dev/2013-March/008441)给出. HTML). (3认同)
  • @ user3580294我认为足够接近.:-)语义上lambda想成为一个函数,但即使在Java 8中也只有基元和对象.所以今天的lambda实现是一个对象,你可以在其上调用`getClass()`等,但结果是未指定的,可能会有变化.将lambda*转换为*作为功能接口实现的对象可能更精确. (3认同)
  • @Xkynar是的,没问题!如有疑问,请使用IDE检查代码; 当你将鼠标悬停在某些东西上时,你可以从IDE显示的类型中学到很多东西.添加了我的推测,希望它有所帮助.一旦熟悉了Java,就应该考虑学习一种函数式语言(Haskell似乎很受欢迎;我的学校教授OCaml).这是一个完全不同的视角,至少在这个案例中至少给出了Java的lambda实现决策背后的一些推理. (2认同)