我正在做一些练习以更好地理解 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 ofthis
.
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 isT
.
T
,这里是 Solution
类,因为它是匿名 Solution
子类和 getName 的最内层封闭类型()
是它的成员。
然后,JLS 状态
Otherwise, let
T
be the enclosing type declaration of which the method is a member, and letn
be an integer such thatT
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 ofthis
.
同样,T
是 Solution
,这是第一个词法封闭类型,因为其声明立即包含方法调用的类是匿名 Solution
子类. this
是匿名的 Solution
子类实例。因此,目标引用是 this
的第一个词法封闭实例,即。 Solution
实例,其 name
字段初始化为值 "main"
。这就是原始代码打印 "main"
的原因。
关于java - 为什么 method() 和 super.method() 在匿名子类中引用不同的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51144423/