为什么超级方法不可见/无法解析? 接口有问题{ void方法(); } 班级家长{ void方法(int arg){} } 类子级扩展父级{ 无效测试(){ 新问题(){ @重写公共void方法(){ //javac错误:类中的方法无法应用于给定类型; //必需:无参数,找到:int 方法(0); Child.this.method(0);//工作正常 Child.super.method(0);//工作正常 } }; } }
IntelliJ IDEA也给出了一个警告: 方法“Method()”无限递归,只能通过引发异常结束 显性总是比隐性好!为什么超级方法不可见/无法解析? 接口有问题{ void方法(); } 班级家长{ void方法(int arg){} } 类子级扩展父级{ 无效测试(){ 新问题(){ @重写公共void方法(){ //javac错误:类中的方法无法应用于给定类型; //必需:无参数,找到:int 方法(0); Child.this.method(0);//工作正常 Child.super.method(0);//工作正常 } }; } },java,visibility,javac,overloading,Java,Visibility,Javac,Overloading,IntelliJ IDEA也给出了一个警告: 方法“Method()”无限递归,只能通过引发异常结束 显性总是比隐性好! method(0)实际上是this.method(0)它实际上是Child$1。this.method(0)和Child$1。this.method(int)在problemble的声明中不存在 编译器和IDE的错误消息对此进行了解释 编译器告诉您这正是它正在做的事情,它正在解析到最局部的范围并找到一些不正确的东西,然后停止查找 您正在这样做: @Override publi
method(0)
实际上是this.method(0)
它实际上是Child$1。this.method(0)
和Child$1。this.method(int)
在problemble
的声明中不存在
编译器和IDE的错误消息对此进行了解释
编译器告诉您这正是它正在做的事情,它正在解析到最局部的范围并找到一些不正确的东西,然后停止查找
您正在这样做:
@Override public void method(){
//javac错误:类中的方法无法应用于给定类型;
//必需:无参数,找到:int
方法(0);
Child.this.method(0);//工作正常
Child.super.method(0);//工作正常
}
这实际上隐含着以下含义:
@Override public void method(){
//javac错误:类中的方法无法应用于给定类型;
//必需:无参数,找到:int
this.method(0);//这在上面的代码中是隐含的
//并解决有问题的声明
Child.this.method(0);//如果上一个调用被实际更正,则永远不会到达。
Child.super.method(0);//也永远不会到达
}
this.method(0)
是无效代码,如果调用this.method()
它将无限递归并抛出StackOverflow
错误
编译器和IDE的错误消息对此进行了解释
这就是范围解析的工作原理,没有什么神秘的原因,阅读范围解析规则,您将看到它首先查找This.XXX
,然后扩展范围
如果您的目标是在
子类上调用方法(int)
,您已经知道如何做了,那么您必须使用子类调用它。由于名称空间范围解析,这个.method(int)
,它必须是完全限定的。子类中的重载隐藏父类中正在重载的方法。在这种情况下,problemble.method()
重载并隐藏父.method(int)。
如果表单是MethodName
,即只是一个标识符,则:
如果标识符出现在可见方法声明的范围内
使用该名称(§6.3,§6.4.1),然后:
- 如果有一个包含该方法的类型声明,则将
T
作为此类类型声明的最内层。班级或
搜索界面是T
- 此搜索策略称为“梳规则”。在查找之前,它会在嵌套类的超类层次结构中有效地查找方法
用于封闭类及其超类层次结构中的方法。看见
§6.5.7.1为例
- 否则,由于一个或多个静态导入或按需静态导入声明,可见方法声明可能在范围内。
没有要搜索的类或接口,例如要调用的方法
稍后确定(§15.12.2.1)
您正在调用匿名内部类中的方法,该类是problemble
的子类型。这使得Child
成为其封闭类型。在您的例子中,T
是匿名内部类,因为它是最内部的类型。因此,要搜索该方法的类是T
,即problem
的匿名子类
在的步骤中,决定方法problem 35; method()
不接受任何参数,因为它没有声明任何参数。因此,它不适用,并引发编译器错误。请参阅:
阴影
如果特定范围(如内部类或方法定义)中的类型声明(如成员变量或参数名)与封闭范围中的另一个声明具有相同的名称,则该声明将隐藏封闭范围的声明
实际上为什么是这样?为什么当您将有问题的#方法
重命名为其他方法(与父方法的名称不同)时,这个问题就消失了?内部类可以调用容器类中的方法而不必对其进行限定。通常情况下。奇怪的是方法(0)
不是读取为对容器类中完全匹配的方法的调用。如果将方法(0)
更正为method()
则调用了另一个方法:Parent.method(int)
与Child$1.method()
定义为problemble.method()
。我怀疑只有在没有名称冲突的情况下,内部类才能调用外部类的方法而不使用限定符。在其他情况下,meth()
是this.meth()
。关于范围解析如何工作的这一点实际上可能是问题的答案,但所有关于OP不理解接口的内容似乎完全是对问题的误读。我认为他的意思是Child$1.method()
Child$1.method()
清除不是重载Parent.method(int)
,因为子$1
不在
interface Problematic {
void method();
}
class Parent {
void method(int arg) { }
}
class Child extends Parent {
void test() {
new Problematic() {
@Override public void method() {
// javac error: method method in class <anonymous Problematic> cannot be applied to given types;
// required: no arguments, found: int
method(0);
Child.this.method(0); // works just fine
Child.super.method(0); // works just fine
}
};
}
}
@Override public void method() {
// javac error: method method in class <anonymous Problematic> cannot be applied to given types;
// required: no arguments, found: int
method(0);
Child.this.method(0); // works just fine
Child.super.method(0); // works just fine
}
@Override public void method() {
// javac error: method method in class <anonymous Problematic> cannot be applied to given types;
// required: no arguments, found: int
this.method(0); // this is implied in the above code
// and resolves to the Problematic declaration
Child.this.method(0); // will never be reached if the previous call is actually corrected.
Child.super.method(0); // will never be reached either
}