Lambda表达式与匿名内部类的联系和区别
Java Lambda 表达式的一个重要用法是简化某些匿名内部类的写法,因此它可以部分取代匿名内部类的作用。
Lambda 表达式与匿名内部类的相同点如下:
下面程序示范了 Lambda 表达式与匿名内部类的相似之处。
与匿名内部类相似的是,由于 Lambda 表达式访问了 url 局部变量,因此该局部变量相当于有一个隐式的 final 修饰,因此同样不允许对 url 局部变量重新赋值。
当程序使用 Lambda 表达式创建了 Displayable 的对象之后,该对象不仅可调用接口中唯一的抽象方法,也可调用接口中的默认方法,如上面程序代码第 26 行所示。
Lambda 表达式与匿名内部类主要存在如下区别。
对于 Lambda 表达式的代码块不允许调用接口中定义的默认方法的限制,可以尝试对上面的 LambdaAndInner.java 程序稍做修改,在 Lambda 表达式的代码块中增加如下一行:
Lambda 表达式与匿名内部类的相同点如下:
- Lambda 表达式与匿名内部类一样,都可以直接访问 effectively final 的局部变量(如果不了解 Effectively final,可先阅读《Java8新特性之Effectively final》一节),以及外部类的成员变量(包括实例变量和类变量)。
- Lambda 表达式创建的对象与匿名内部类生成的对象一样,都可以直接调用从接口中继承的默认方法。
下面程序示范了 Lambda 表达式与匿名内部类的相似之处。
@FunctionalInterface interface Displayable { // 定义一个抽象方法和默认方法 void display(); default int add(int a, int b) { return a + b; } } public class LambdaAndInner { private int age = 12; private static String name = "新宝库"; public void test() { String url = "https://www.xinbaoku.com/"; Displayable dis = () -> { // 访问的局部变量 System.out.println("url 局部变量为:" + url); // 访问外部类的实例变量和类变量 System.out.println("外部类的 age 实例变量为:" + age); System.out.println("外部类的 name 类变量为:" + name); }; dis.display(); // 调用dis对象从接口中继承的add()方法 System.out.println(dis.add(3, 5)); } public static void main(String[] args) { LambdaAndInner lambda = new LambdaAndInner(); lambda.test(); } }输出结果为:
url 局部变量为:https://www.xinbaoku.com/
外部类的 age 实例变量为:12
外部类的 name 类变量为:新宝库
8
与匿名内部类相似的是,由于 Lambda 表达式访问了 url 局部变量,因此该局部变量相当于有一个隐式的 final 修饰,因此同样不允许对 url 局部变量重新赋值。
当程序使用 Lambda 表达式创建了 Displayable 的对象之后,该对象不仅可调用接口中唯一的抽象方法,也可调用接口中的默认方法,如上面程序代码第 26 行所示。
Lambda 表达式与匿名内部类主要存在如下区别。
- 匿名内部类可以为任意接口创建实例——不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方法即可;但 Lambda 表达式只能为函数式接口创建实例。
- 匿名内部类可以为抽象类甚至普通类创建实例;但 Lambda 表达式只能为函数式接口创建实例。
- 匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;但 Lambda 表达式的代码块不允许调用接口中定义的默认方法。
对于 Lambda 表达式的代码块不允许调用接口中定义的默认方法的限制,可以尝试对上面的 LambdaAndInner.java 程序稍做修改,在 Lambda 表达式的代码块中增加如下一行:
// 尝试调用接口中的默认方法,编译器会报错
System.out.println(add(3, 5));
public void test() { String url = "https://www.xinbaoku.com/"; Displayable dis = new Displayable() { @Override public void display() { // 访问的局部变量 System.out.println("url 局部变量为:" + url); // 访问外部类的实例变量和类变量 System.out.println("外部类的 age 实例变量为:" + age); System.out.println("外部类的 name 类变量为:" + name); System.out.println(add(3, 5)); } }; dis.display(); }
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算