super的优先级高于外级吗?
考虑我们有三个班级:
ClassA.java:
public class ClassA {
protected String var = "A Var";
public void foo() {
System.out.println("A foo()");
}
}
ClassB.java:
public class ClassB {
private String var = "B Var";
public void test() {
new ClassA() {
public void test() {
foo();
System.out.println(var);
}
}.test();
}
public void foo() {
System.out.println("B foo()");
}
}
当我调用new ClassB().test()
时,我得到以下输出(这是非常期待的):
A foo()
A Var
问题:它是在某个地方定义的,内部类首先从超类中获取(方法和成员),然后从外部类中定义,还是 JVM 编译器实现依赖?我查看了JLS(§15.12.3),但找不到任何参考,也许有人指出但是我误解了一些术语?
答案 0 :(得分:5)
请参阅6.3.1 Shadowing Declarations:
名为 n 的方法的声明 d 会影响封闭范围内名为 n 的任何其他方法的声明 d 在 d 的整个范围内发生。
哪个可能被解释为“foo
的声明(继承自ClassA
)会影响名为foo
的任何其他方法的声明在ClassB
的整个范围内,在foo
发生的位置封闭范围(foo
)。
也相关 - 第15.12.1部分:
15.12.1编译时步骤1:确定要搜索的类或接口
在编译时处理方法调用的第一步是确定要调用的方法的名称以及检查该名称的方法定义的类或接口。根据左括号前面的形式,有几种情况需要考虑,如下所示:
- 如果表单是 MethodName ,则有三个子句:
- 如果它是一个简单的名称,即只是一个标识符,那么该方法的名称就是标识符。如果标识符出现在具有该名称的可见方法声明的范围(第6.3节)中,则必须存在该方法所属的封闭类型声明。设T是最里面的类型声明。 要搜索的类或界面为T 。
- 如果它是TypeName.Identifier形式的限定名称,则[...]
- 在所有其他情况下,限定名称的格式为FieldName.Identifier;然后[...]
答案 1 :(得分:1)
我认为你总是得到"A var"
。
这是因为您的test()
方法实现是在A
的匿名子类上定义的。除非您使用B.var
明确引用外部类,否则我认为您无法访问test()
方法中的ClassB.this.var
实例变量。