"this"的值在一个匿名类vs一个lambda表达式中 [英] Value of "this" in an anonymous class vs a lambda expression

查看:154
本文介绍了"this"的值在一个匿名类vs一个lambda表达式中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对匿名类和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

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

解决方案

在lambda表达式中,this用词法绑定到周围的类,而在匿名类中this用词法绑定到匿名的类./p>

Java语言规范在 15.27.2 :

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

lambda表达式主体中的this(显式和隐式)的透明性(即,与周围环境中相同)将为实现提供更大的灵活性,并避免了正文中不合格的名称取决于重载分辨率.

实际上,lambda表达式需要谈论自己(以递归方式调用自身或调用其其他方法)是不寻常的,而使用名称来引用事物则更为常见在封闭的类中否则将被遮盖(thistoString()).如果必须让lambda表达式引用其自身(例如通过this进行引用),则应改用方法引用或匿名内部类.

为了从匿名类内部引用周围类的this,您将必须使用

When using an anonymous class:

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

Can someone please explain the different behavior?

In a lambda expression, this is lexically bound to the surrounding class, while in the anonymous class this is lexically bound to the anonymous class.

The Java Language Specification describes this behavior at 15.27.2:

Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).

The transparency of this (both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.

Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (this, toString()). If it is necessary for a lambda expression to refer to itself (as if via this), a method reference or an anonymous inner class should be used instead.

In order to reference this of the surrounding class from inside an anonymous class, you will have to use a qualified this.

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

这篇关于"this"的值在一个匿名类vs一个lambda表达式中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆