Java匿名内部类和Lambda表达式
匿名内部类
有时候我们需要临时创建一个类和对象并且这个类无需在其他地方复用,就可以使用匿名内部类。
匿名内部类的好处是不需要单独开一个类文件来编写,也不需要类名称,临时使用很方便。
但是匿名内部类没有名字也就没有构造器,不能直接实例化。
同时匿名内部类只能实现一个接口,这一点从使用方式上就可以看出来。
实现接口的匿名内部类
匿名内部类多用于临时实现一个接口,可以直接现场定义并实例化。
定义规则:
Interface in = new Interface() {
}
这里看上去是new一个接口实际上这里是语法糖,Java实际上是新建了一个实现该接口的类然后new这个类。
函数式接口
如果一个接口只定义了一个接口方法,那么该接口称为函数式接口。
实际上类中的方法本质是一个函数,只实现一个方法的类使用起来就好像在使用这个函数。
函数式接口可以用@FunctionalInterface注解标注,编译器会帮你检测是否为一个函数式接口。
实现一个函数式接口的匿名内部类可以简写为Lambda表达式。
因为只实现一个方法,那么只要定义好了这个方法就等于定义好了这个匿名内部类。
那么对于这个方法的实现就可以抽出来,于是有了Lambda表达式。
Lambda表达式仍然是语法糖,Java后台根据表达式的定义创建了一个匿名内部类并实例化。
Lambda表达式只需要定义逻辑,甚至不需要声明入参类型,因为这些都可以从接口中推断出来。
函数式编程风格
函数式编程是说函数是第一公民,函数作为变量,可以接收函数,也可以返回函数。
Java没有函数,只能传入对象,所以使用匿名内部类来实现函数式编程的风格。
历史上研究函数式编程的理论是Lambda演算,所以我们经常把支持函数式编程的编码风格称为Lambda表达式。
看一个例子
- 定义一个函数式接口
public interface Food {
String getFood(String name);
}
- 有一个方法要传入实现该接口的对象
public class Demo4 {
// eat方法要传入Food对象
public static void eat(Food f) {
String food = f.getFood("ham");
System.out.println("eating " + food);
}
// 匿名内部类
public static void main(String[] args) {
Demo4.eat(new Food() {
@Override
public String getFood(String name) {
return name;
}
});
// Lambda表达式
Demo4.eat(name -> {
return name;
});
// 如果只有return xxx 一行代码,则可以简写
Demo4.eat(name -> name);
}