Java中的匿名类与Lambda表达式

匿名类

匿名类是一个没有名称的内部类,并且只能创建一个对象实例。当要实现某些“额外”功能(例如类或接口的重载方法)来创建对象的实例时,匿名类可能很有用,这时不必实际子类化。

匿名类主要以两种方式创建:

  • 继承类(可以是抽象的或具体的)
  • 实现接口

Java引入了匿名类的创建,以减少代码复杂性。如果我们创建一个单独的类来实现一个接口并使用它的实例来调用该方法,则会产生开销。而当我们从不在其他任何地方使用该类的话这个开销就会显得有些浪费。在这种情况下,我们可以使用匿名类,它们既可以在方法主体内部创建,也可以作为方法参数创建。

Lambda表达式

Lambda表达式是Java 8中引入的一项新功能。Lambda表达式是一个匿名函数。没有名称且不属于任何类的函数。

Lambda表达式是用来表示功能接口的实例(具有单一抽象方法的接口称为功能接口。比如java.lang.Runnable)。lambda表达式实现其中唯一的抽象函数,这个接口被称为函数式接口。

要创建lambda表达式,我们在lambda运算符->的左侧指定输入参数(如果有的话),然后将表达式或语句块放在lambda运算符的右侧。例如,lambda表达式:(x,y)-> x + y
指定lambda表达式有两个参数x和y并返回它们的和。

// lambda表达式的语法
(parameter_list )-> { function_body }

lambda表达式提供了以下功能:

  • 启用可将功能视为方法参数,或将代码视为数据。
  • 可以创建而不属于任何类的函数。
  • 可以将lambda表达式作为对象传递并按需执行。

程序示例

接口

public interface Animal {
    public void eat();
}

常规接口实现

public class SeaAnimal implements Animal{

    @Override
    public void eat() {
        System.out.println("SeaAnimal class implementing eat()");
    }

}

public class Test {
    public static void main(String[] args) {
        Animal animal = new SeaAnimal();
        animal.eat();
    }
}

匿名类

public class Test1 {
    public static void main(String[] args) {
        Animal animal = new Animal() {

            @Override
            public void eat() {
                System.out.println("Anonymous class implementing eat()");
            }

        };

        animal.eat();
    }
}

Lambda表达式

public class Test2 {
    public static void main(String[] args) {
        Animal animal = ()->System.out.println("Lambda Expression implementing eat()"); 
        animal.eat();
    }
}

我们可以看到使用Lambda表达式如何使代码更简单。但是请注意,并非所有匿名类都可以用Lambda表达式代替。

它们之间的区别

匿名类 Lambda表达式
没有名字的类 没有名称的方法(匿名函数)
它可以扩展抽象或具体的类 它不能扩展抽象或具体的类
它可以实现包含任何抽象方法的接口 它可以实现一个包含单个抽象方法的接口
匿名类可以具有实例变量和方法局部变量 Lambda表达式只能具有局部变量
可以实例化匿名内部类 Lambda 表达式无法实例化
在匿名内部类内部,“ this”始终是指当前匿名内部类对象,而不是外部对象 在Lambda表达式内部,“ this”始终引用当前的外部类对象,即包围类对象
如果我们要处理多种方法,这是最佳选择 如果我们要处理接口,这是最佳选择
在编译时,将生成一个单独的.class文件 在编译时,不会生成单独的.class文件。只是将其转换为外部类的私有方法
每当我们创建对象时,内存分配都是按需的 它驻留在JVM的永久内存中

推荐阅读更多精彩内容