Java Lambdas和Runnable

Java Lambdas和Runnable,java,lambda,Java,Lambda,我的理解是,Lambda的表达式用于替换抽象实现周围的锅炉板代码。 因此,如果我必须创建一个新线程,它接受一个可运行的接口(函数), 我不必创建新的匿名类,然后提供void run(),然后在其中写入逻辑 相反,您可以简单地使用lambda并将其指向方法,前提是方法签名与run相同,即不接受任何内容,也不返回任何内容 然而,我无法理解下面的实现 Thread t= new Thread(()->printStudent(stud)); public static void printSt

我的理解是,Lambda的表达式用于替换抽象实现周围的锅炉板代码。 因此,如果我必须创建一个新线程,它接受一个可运行的接口(函数), 我不必创建新的匿名类,然后提供void run(),然后在其中写入逻辑 相反,您可以简单地使用lambda并将其指向方法,前提是方法签名与run相同,即不接受任何内容,也不返回任何内容

然而,我无法理解下面的实现

Thread t= new Thread(()->printStudent(stud));

public static void printStudent(Student stud) {
        System.out.println("Student is "+ stud);
    }
在上面的例子中,printStudent接受一个参数(与runnable的run()方法不同),尽管它以某种方式工作


这是如何工作的?

您没有将参数传递给
run()
方法,而是
()->
部分表示
run()
方法。您所做的只是将方法定义为:

 @Override
 public void run(){
      printStudent(stud); //the value of stud from the context copied here
 }
以下代码(在类中包装/修改代码):

在功能上等同于:

public class Main {

    public static void main(String[] args) {
        String item = "Hello, World!"
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                printItem(item);
            }
        });
        t.start();
    }

    public static void printItem(Object item) {
        System.out.println(item);
    }
}
注意,在第一个示例中,必须使用lambda(
->
)。但是,您将无法使用方法引用,因为方法
printItem
Runnable
的签名不匹配。这是非法的:

Thread t = new Thread(Main::printItem);
基本上,方法参考与:

new Runnable() {
    @Override
    public void run() {
        printItem(); // wouldn't compile because the method has parameters
    }
}
->
之后的表达式,或
->{}
块中的代码,与您在
run()
方法中放置的代码相同

Runnable singleExpression = () -> /* this is the code inside run()*/;
Runnable codeBlock = () -> {
    // this is the code inside run()
};

stud
变量在封闭范围内定义。该变量的值作为参数传递。因为lamdba不像匿名类,它的
this
引用外部类的
this
。同样,java streams中的方法引用也是如此。匿名类是如何实现的?我们是说java内部会创建一个匿名类,该类将Student作为实例变量,并通过我们传递的任何内容来丰富它?我不会这么说。它们转换为字节码的方式不同,即运行时行为。简单地说,匿名类被实例化并作为每个引用的类加载,而lambda表达式在所谓的函数接口中被动态调用(这是一条JVM指令)。
Runnable singleExpression = () -> /* this is the code inside run()*/;
Runnable codeBlock = () -> {
    // this is the code inside run()
};