java - 为什么 method() 和 super.method() 在匿名子类中引用不同的东西?

标签 java inheritance inner-classes

我正在做一些练习以更好地理解 Java 中的内部类是如何工作的。我发现了一个非常有趣的练习。练习的条件是使 printName() 打印“sout”而不是“main”,并进行最小的更改。有它的代码:

public class Solution {
    private String name;

    Solution(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

    private void sout() {
        new Solution("sout") {
            void printName() {
                System.out.println(getName());
                // the line above is an equivalent to:
                // System.out.println(Solution.this.getName);
            }
        }.printName();
    }

    public static void main(String[] args) {
        new Solution("main").sout();
    }
}

我们遇到了一个有趣的情况——这两个类有 is-A 和 has-A 连接。 这意味着匿名内部类扩展了外部类,并且内部类的对象也引用了外部类的对象。 如果您运行上面的代码,将打印“main”。子级不能通过继承调用父级的getName()。但是作为内部类的子级使用对父级(外部类)的引用来访问该方法。

解决此任务的最简单方法是将 getName() 的访问修饰符从 private 更改为其他任何内容。因此, child 能够通过继承使用 getName(),并且由于后期绑定(bind),“sout”将被打印出来。

解决此任务的另一种方法是使用super.getName()

private void sout() {
    new Solution("sout") {
        void printName() {
            System.out.println(super.getName());
        }
    }.printName();
}

而且我无法理解它是如何工作的。有人可以帮我理解这个问题吗?

感谢您的尝试)

最佳答案

Java 语言规范 (JLS),in the context of the compiler resolving a method invocation expression , 状态

If the form is super . [TypeArguments] Identifier, then the class to search is the superclass of the class whose declaration contains the method invocation.

其声明包含方法调用,在这种情况下,是匿名Solution 子类,其父类(super class)是Solution。 JLS,in the context of determining which instance will be used to invoke the method , 然后继续说

If the form is super . [TypeArguments] Identifier, then the target reference is the value of this.

this,在这种情况下,指的是匿名 Solution 子类的实例。该实例的 name 字段已使用值 "sout" 初始化,因此 getName() 返回。


在原始样本中,

new Solution("sout") {
    void printName() {
        System.out.println(getName());
    }
}.printName();

getName() 方法调用是不合格的,因此适用不同的规则。也就是

If there is an enclosing type declaration of which that method is a member, let T be the innermost such type declaration. The class or interface to search is T.

T,这里是 Solution 类,因为它是匿名 Solution 子类和 getName 的最内层封闭类型() 是它的成员。

然后,JLS 状态

Otherwise, let T be the enclosing type declaration of which the method is a member, and let n be an integer such that T is the n'th lexically enclosing type declaration of the class whose declaration immediately contains the method invocation. The target reference is the n'th lexically enclosing instance of this.

同样,TSolution,这是第一个词法封闭类型,因为其声明立即包含方法调用的类是匿名 Solution 子类. this 是匿名的 Solution 子类实例。因此,目标引用是 this 的第一个词法封闭实例,即。 Solution 实例,其 name 字段初始化为值 "main"。这就是原始代码打印 "main" 的原因。

关于java - 为什么 method() 和 super.method() 在匿名子类中引用不同的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51144423/

相关文章:

java - 将方法与返回的 jcomponents 和泛型一起使用

java - IntelliJ 说它无法解析 getValue()

python - 继承和聚合类属性

java - 在外部类的构造函数中实例化内部类是否危险? ( java )

java - 将 'form-data' 设置为 Jersey 客户端发布请求

java - 按第一个元素对字符串数组列表进行排序

java - 抽象类为 parcelable

java - 非静态变量的引用

java - 用spring创建内部类

java - OuterClass.this.someMethod() 背后的基本原理是什么?