面试题答案
一键面试语法区别
- Lambda表达式:语法简洁,主要由参数列表、箭头符号
->
和代码块组成。例如,对于一个接受两个整数并返回它们之和的函数式接口BiFunction<Integer, Integer, Integer>
,Lambda表达式写法为(a, b) -> a + b
。无需像匿名类那样显式声明接口类型,参数类型也常可由编译器推断。 - 传统匿名类:语法较为冗长,需要完整声明类实现接口或继承类,包含
new
关键字、类定义及方法重写等。例如同样实现上述BiFunction
接口,匿名类写法为new BiFunction<Integer, Integer, Integer>() { @Override public Integer apply(Integer a, Integer b) { return a + b; } };
性能区别
- Lambda表达式:在Java 8及之后版本,Lambda表达式在编译时会进行优化,生成的字节码更加紧凑高效。运行时,JVM对Lambda表达式有专门的优化机制,比如方法内联等,对于简单的函数式操作,性能表现通常较好。
- 传统匿名类:由于匿名类需要创建额外的类文件和实例,在内存占用和创建开销上相对较大。每次创建匿名类实例都会有类加载、实例初始化等开销,对于频繁创建实例的场景,性能不如Lambda表达式。
使用场景区别
- Lambda表达式:
- 函数式编程场景:非常适合用于集合的遍历、过滤、映射等操作,如
List<Integer> numbers = Arrays.asList(1, 2, 3, 4); numbers.stream().map(n -> n * 2).forEach(System.out::println);
。 - 简单的事件处理:在一些简单的事件监听场景中,Lambda表达式可以使代码更简洁,例如JavaFX中的事件处理。
- 函数式编程场景:非常适合用于集合的遍历、过滤、映射等操作,如
- 传统匿名类:
- 需要复杂逻辑或状态维护:当实现的接口方法需要复杂逻辑、需要维护内部状态或需要访问外部类非final变量时,匿名类更为合适。例如在一个图形绘制库中,匿名类实现绘图接口,内部可以维护一些绘图状态。
- 兼容旧代码:在一些旧代码库中,可能仍然依赖匿名类的方式来实现接口,为了保持兼容性,会继续使用匿名类。