Java8 教程

Java8 Lambda和匿名内部类的对比

匿名内部类和 Lambda 表达式都可以用来实现一个函数接口(Functional Interface)的实例,本章将通过一个实例来介绍二者的区别。

我们先来看一个实例,启动一个线程向控制台输出一个字符串。

(1)匿名内部类实现方式:

package com.hxstrive.jdk8.lambda_theory;

/**
* 匿名实现方式
* @author hxstrive.com
*/
public class AnonymousDemo {

   public static void main(String[] args) {
       new Thread(new Runnable() {
           @Override
           public void run() {
               System.out.println("匿名实现方式");
           }
       }).start();
   }

}

(2)Lambda 实现方式:

package com.hxstrive.jdk8.lambda_theory;

/**
* Lambda实现方式
* @author hxstrive.com
*/
public class LambdaDemo {

   public static void main(String[] args) {
       new Thread(() -> {
           System.out.println("Lambda实现方式");
       }).start();
   }

}

两者区别

匿名内部类和 Lambda 表达式的主要区别如下:

代码量

从代码量上比较,Lambda 表达式的语法更加精简,代码量相对较小,而且可读性更强,降低了程序员的输入疲劳度。而匿名内部类语法冗长,代码量较大。

语法形式

匿名内部类是 Java 的一种特性,语法形式比较冗长,需要使用关键字、大括号、分号等,使用起来稍显繁琐。而 Lambda 表达式是从 JDK8 开始引入的,语法简单,可以看作是对匿名内部类的一种简化和优化。

类型推导和函数接口

在使用 Lambda 表达式时,JDK8 可以推导出 Lambda 表达式的参数类型和返回类型。因此,使用 Lambda 表达式时不需要显示声明类型。而匿名内部类需要显式地声明接口和类类型。例如:

boolean flag = test((Integer val) -> {
   if(val > 100) {
       return true;
   }
   return false;
}, 120);
System.out.println("flag=" + flag);

对上下文变量的捕获

匿名内部类中可以访问外部类的成员变量、方法参数和本地变量,它们的值都可以在匿名内部类中被修改。而 Lambda 表达式中只能捕获最终变量或者是事实上的最终变量(final 或者等价于 final),也就是只能读取外部变量,不能修改。如果需要修改则使用会报编译错误,如下:

java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量

内部状态

匿名接口实现可以有状态(成员变量),而 lambda 表达式则不能。请看这个接口:

public interface MyEventConsumer {
    public void consume(Object event);
}

这个接口可以使用匿名接口实现,就像下面这样:

MyEventConsumer consumer = new MyEventConsumer() {  
    public void consume(Object event){
        System.out.println(event.toString() + " consumed");
    }
};

这个匿名的 MyEventConsumer 实现可以拥有自己的内部状态。看看这个重写的代码:

MyEventConsumer myEventConsumer = new MyEventConsumer() {
    // 内部状态
    private int eventCount = 0;
    
    public void consume(Object event) {
        System.out.println(event.toString() + " consumed " + this.eventCount++ + " times.");
    }
};

请注意,匿名 MyEventConsumer 的实现,现在有了一个名为 eventCount 的字段。lambda 表达式不能有这样的字段,因此 lambda 表达式可以说是无状态的。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号