为什么超级方法不可见/无法解析? 接口有问题{ void方法(); } 班级家长{ void方法(int arg){} } 类子级扩展父级{ 无效测试(){ 新问题(){ @重写公共void方法(){ //javac错误:类中的方法无法应用于给定类型; //必需:无参数,找到:int 方法(0); Child.this.method(0);//工作正常 Child.super.method(0);//工作正常 } }; } }

为什么超级方法不可见/无法解析? 接口有问题{ 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

IntelliJ IDEA也给出了一个警告:

方法“Method()”无限递归,只能通过引发异常结束

显性总是比隐性好!
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
}