Fari

java中匿名内部类和lambda的区别

对于只有一个抽象方法的接口,可以使用匿名内部类创建引用对象,也能使用lambda表达式来创建对象:

interface I {
    void p();
}

// 使用匿名内部类创建对象
I imp = new I() {
    @Override
    public void p() {
        System.out.println("aaaa");
    }
};

// 使用lambda表达式创建对象
I imp = () -> System.out.println("bingo");

两者的区别在于:前者是在字节码层面创建了一个接口的实现类然后进行初始化,后者则使用了动态语言的特性:

如何解释这个动态语言特性呢?

对于第一种方法,它的引用类型是固定的,即它只能是 I,不能替换成其他接口,而对于第二种,它的引用类型可以修改成任意其他只有一个抽象方法的接口

这是不是和java原本的强类型不太一样了,原本的强类型是指静态类型和实际类型一一对应,显然这里并不是这样。

为了使得java也具有动态类型的特性,jdk7引入了invokedynamic字节码指令,事实上,如果仅对于java语言来说,它早就可以通过反射实现动态语言的特性,之所以还要引入该指令,是因为反射是java语言的特性,而jvm不仅仅能运行java代码。

Tags: