理解抽象类的超级关键字

St.*_*rio 12 java super

考虑以下课程:

public abstract class AbstractClass {

    public abstract String m();

    public AbstractClass get(){
        return new AbstractClass() {

            @Override
            public String m() {
                return "Anonymous " + super.m(); //1, Compile-time erro
            }
        };
    }

}
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚为何super禁止这种使用.在//1,发生以下错误

Cannot directly invoke the abstract method m() for the type AbstractClass
Run Code Online (Sandbox Code Playgroud)

所以,我咨询了JLS 15.11.2并没有找到阻止这些代码编译的限制.他们来了:

  1. 明显

如果使用关键字super的表单出现在Object类的声明中,那么这是一个编译时错误,因为Object没有超类.

  1. 由于不可能有一个实例AbstractClass,但只有一个具体的子类,以下似乎也是有效的:

使用关键字super的表单仅在实例方法,实例初始值设定项或构造函数中有效,或在类的实例变量的初始值设定项中有效.如果它们出现在其他任何地方,则会发生编译时错误.

  1. 不是这样的.

如果当前类不是类T或T本身的内部类,则它是编译时错误.

当然,我可以使用AbstractClass.this.m(),但这不是我要问的.

Chr*_*s K 16

super关键字在这里不起作用,因为它AbstractClass.m()已被声明为abstract,因此在内部类的父级上没有合适的实现.请记住,内部类不扩展外部类(即使它是相同的类型),它们包含对它的引用.

但是当从内部类调用外部类(这是我认为你打算在这里做)时,请使用以下语法AbstractClass.this.m().

以下内容将按预期编译和工作.

public abstract class AbstractClass {

    public abstract String m();

    public AbstractClass get(){
        return new AbstractClass() {

            @Override
            public String m() {
                return "Anonymous " + AbstractClass.this.m(); 
            }
        };
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 旁注:如果你坚持使用get()返回的AbstractClass,不要忘记它仍将保持对你调用get()的原始AbstractClass的引用.如果您删除对该原始对象的引用并期望它获得GC,则这一点变得很重要......它不会.这是导致意外内存泄漏的常见问题. (2认同)

Ale*_*exN 6

据我所知,编译器在使用时尝试使用静态绑定super.m();.由于没有方法,super.m();因为它是抽象的,编译器已经在编译时抱怨.

Java中的静态绑定意味着在编译期间解析方法,而在运行时使用可被多个子类覆盖的方法时发生动态绑定.