在定义一个抽象类或接口以后,我们无法将其直接实例化。那么怎么将其实例化呢?最容易想到的是再定义一个类,并继承这个抽象类(或实现这个接口),然后把抽象方法补全,就可以对这个子类进行实例化了。那么实际应用中,定义如此多个class是比较繁琐的,因此这里引入了匿名内部类和Lambda表达式的概念。
匿名内部类
首先看一段简单的代码:
interface Behavior {
void eat(String food);
void speak(String person, String content);
int add(int a, int b);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Behavior b = new Behavior() {
public void eat(String food) {
System.out.println("I am eating " + food);
}
public void speak(String person, String content) {
System.out.println(person + " is speaking " + content);
}
public int add(int a, int b) {
return a + b;
}
};
b.eat("apple");
b.speak("Tom", "Chinese");
System.out.println(b.add(3, 4));
}
在上面的代码中,我们定义了一个接口Behavior。由于接口中含有抽象方法,因此不能直接实例化,必须通过其他类来实现它。但是在main方法中,这个接口直接被new了,同时在后面的大括号中,将这个接口的三个抽象方法都实现了。
可见在实现上述代码中,我们并没有实际声明一个类,来实现Behavior。但是,我们new的这个对象,却可以理解成有一个匿名类(没有声明的)实现了接口中的所有方法,且对这个匿名类进行了实例化, b 则是这个对象的引用。
由此可见,通过匿名内部类这种思想,一定程度上简化了代码,不用编写很多的class。
Lambda表达式
在使用匿名内部类时,编译后去查看class文件,依然可以看到额外生成一些class文件。但如果使用Lambda表达式就不会。
Lambda也称为闭包,是Java8出现的新特性。它允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑,但同时会降低程序的可读性且有一定的局限性。
注意:使用Lambda表达式的条件,对应接口中只有一个抽象方法!
看一段代码:
interface Drink {
void drink(String liquid);
}
interface Play {
void play(String person, String item);
}
interface Add {
int add(int a, int b);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Drink d1 = l -> System.out.println("drink " + l);
d1.drink("Cola");
Play p1 = (p, i) -> System.out.println(p + " play " + i);
p1.play("Jack", "Basketball");
Add a1 = (a, b) -> {return a + b;};
int sum = a1.add(3, 4);
System.out.println(sum);
}
在上面的代码中,有三个Lambda表达式。Lambda表达式通过符号 -> 将两部分隔离开,前面的部分为参数,后面的部分是抽象方法具体的执行内容。
对main中第一行代码来说, 表示参数字符串(前面的String类型可以省略),-> 后面的内容表示Drink这个类中的抽象方法的具体实现(输出内容到控制台)。
如果Lambda表达式中没有参数,那么在 -> 前的位置上写 ();如果有多个参数,也需要在参数外面加上小括号()。
总结
Lambda表达式主要用来对接口式的匿名内部类进行简化,被称为函数式接口的概念。函数式接口是指只含有一个抽象方法的普通接口,这种接口就可以利用Lambda表达式来简化代码的编写。
参考:
https://www.jianshu.com/p/f258e9464a29