Java 理解抽象类的超关键字
考虑以下类别:Java 理解抽象类的超关键字,java,super,Java,Super,考虑以下类别: public abstract class AbstractClass { public abstract String m(); public AbstractClass get(){ return new AbstractClass() { @Override public String m() { return "Anonymous " + super.m(
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
}
};
}
}
尚不清楚为什么禁止使用super
。在//1
发生以下错误
Cannot directly invoke the abstract method m() for the type AbstractClass
因此,我查阅了数据库,没有发现阻止编译此类代码的限制。这是:
AbstractClass
的实例,但只能有一个具体的子类,因此在我看来,以下内容也是有效的:当然,我可以使用
AbstractClass.this.m()
,但这不是我要问的。据我所知,编译器在使用super.m()时尝试使用静态绑定代码>。因为没有方法super.m()代码>由于它是抽象的,编译器在编译时已经在抱怨了
Java中的静态绑定意味着在编译时解析方法,而在运行时使用可由多个子类重写的方法时会发生动态绑定。super关键字在此处不起作用,因为AbstractClass.m()
已声明为抽象,因此,在内部类的父级上没有合适的实现。请记住,内部类并不扩展外部类(即使它是同一类型),而是包含对它的引用
但是,当从内部类调用外部类(我相信您在这里就是这么做的)时,请使用以下语法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();
}
};
}
}
为什么要在这里调用super.m()
?该方法未在抽象类中实现,因此尝试调用它毫无意义。@Jesper是的,它不是。但正如我已经说过的,它是在conrete类中实现的。我们不能有AbstractClass
本身的实例,只能有它的一个子类。请注意,super.m()
不调用在匿名子类中重写的m
。您告诉Java显式调用超类中的实现。由于该方法在超类中是抽象的,因此无法调用它。(您希望super.m()
做什么?)如果您使用super
调用一个方法,那么查找要调用的方法的正常多态性规则不适用。它将在超类中显式查找,并且不会在子类(JLS 15.12.1)中调用该方法的重写版本。@Jesper是的,现在我明白了,谢谢。如果表格是超级的。NonWildTypeArgumentsPt标识符,则方法的名称是标识符,要搜索的类是其声明包含方法调用的类的超类。旁注:如果保留get()返回的AbstractClass,不要忘记,它仍将保存对您调用get()所针对的原始抽象类的引用。如果您删除对原始对象的引用,并期望它获得GC'd。。。不会的。这是一个常见的问题,它会导致意外的内存泄漏。因此,如果表单是super,请注意。NonWildTypeArgumentsPT标识符,则方法的名称是标识符,要搜索的类是其声明包含方法调用的类的超类。在这里也是相关的,不是吗?@St.Antario是的。super关键字表示“扫描当前对象的对象层次结构以查找方法”。在您的示例中,有两个“AbstractClass”类型的对象,第三个对象是隐含的(但不包括在内),因此存在混淆。这三个是,1)抽象类本身,2)在get()中创建的匿名内部类,以及3)调用get()所需的抽象类的子类。内部类one直接扩展了AbstractClass,因此扫描其父类中的m()将发现没有实现的m()的抽象声明。