"这个"的价值在匿名类vs lambda表达式中

时间:2017-02-27 06:33:00

标签: java lambda java-8 anonymous-class

我对匿名类和lambda表达式的不同行为有点混淆。

当我使用lambda表达式时:

//Test.java

Runnable r1 = () -> System.out.println(this);
Runnable r2 = () -> System.out.println(toString());

@Override
public String toString() {
    return "Hello World!";  
}

// in main method 
new Test().r1.run();
new Test().r2.run();   
Output : Hello World!
         Hello World!

使用匿名类时:

Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println(this);   
    }
};

Runnable r2 = new Runnable() {
    @Override
    public void run() {
        System.out.println(toString()); 
    }
};

@Override
public String toString() {
    return "Hello World!";  
}

// in main method 
new Test().r1.run();
new Test().r2.run();  
Output : Package_Name.Test$1@1db9742
         Package_Name.Test$2@106d69c

有人可以解释不同的行为吗?

1 个答案:

答案 0 :(得分:11)

在lambda表达式中,this在词法上绑定到周围的类,而在匿名类this中,词法绑定到匿名类。

Java语言规范在15.27.2

描述了这种行为
  

与匿名类声明中出现的代码不同,名称的含义以及出现在lambda主体中的thissuper关键字以及引用声明的可访问性与周围的相同上下文(lambda参数引入新名称除外)。

     

lambda表达式主体中this(显式和隐式)的透明度 - 也就是说,将其视为与周围上下文相同 - 允许实现更灵活,并防止身体中不合格名称的含义,不依赖于重载决议。

     

实际上,lambda表达式需要谈论自己(要么递归地调用自身还是调用其他方法)是不常见的,而更常见的是想要使用名称来引用事物在封闭的类中,否则将被遮蔽(thistoString())。如果lambda表达式需要引用它自己(就像通过this),则应该使用方法引用或匿名内部类。

为了从匿名类中引用周围类的this,您必须使用qualified this

Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println(Test.this); // or Test.this.toString()
    }
};