lambda表达式
可以传值
Runnable r1 = () -> {System.out.println(“Hello Lambda!”);};
Object obj = r1;
但是不能这样 Object obj = () -> {System.out.println(“Hello Lambda!”);}; // ERROR! Object is not a functional interface!
必须显式的转型成一个函数式接口才可以:
Object o = (Runnable) () -> { System.out.println("hi"); }; // correct
一个λ表达式只有在转型成一个函数式接口后才能被当做Object使用。所以下面这句也不能编译:
System.out.println( () -> {} ); //错误! 目标类型不明
必须先转型:
System.out.println( (Runnable)() -> {} ); // 正确
假设你自己写了一个函数式接口,长的跟Runnable一模一样:
@FunctionalInterface
public interface MyRunnable {
public void run();
}
那么
Runnable r1 = () -> {System.out.println("Hello Lambda!");};
MyRunnable2 r2 = () -> {System.out.println("Hello Lambda!");};
都是正确的写法。这说明一个λ表达式可以有多个目标类型(函数式接口),只要函数匹配成功即可。
但需注意一个λ表达式必须至少有一个目标类型。
lambda表达式和匿名内部类是有区别的,如果你实现一个匿名内部类然后使用this指向,那么编译后会有2个文件,如果使用lambda表达式,使用this,输出则只有一个文件
Lambda方法体外部并没有匿名内部类,当然只能指向LambdaTest。**更准确地说,this是指向方法的调用者,是隐式传递的。**从这个角度看,Lambda和匿名内部类本质上还是不同的
接口要想接收Lambda表达式,必须是一个函数式接口。所谓函数式接口,最核心的特征是:有且只有一个抽象方法。
也就是说,如果你希望一个接口能接收Lambda表达式充当匿名类对象,那么接口必须仅有一个抽象方法,这是函数式接口的定义。通常我们可以在接口上加一个@FunctionalInterface检测,作用于@Override一样。但函数式接口和@FunctionalInterface注解没有必然联系。
comparto有2个抽象方法还可以使用,是因为有一个为Object的抽象类equals
联系。
Comparator有2个抽象方法还可以使用,是因为有一个为Object的抽象类equals