想象一下,我们有一个班级:
class A {
public void m() {
System.out.println("A - > m()");
}
}
...我希望在类创建上覆盖方法m
,而无需使第二个子类B
扩展A
。
public static void main(String[] args) {
A a = new A() {
@Override
public void m() {
System.out.println("Override - > m()");
new Thread(new Runnable() {
@Override
public void run() {
// I want to be able to call the super method.
// This is illegal!
A.super.m();
}
}).start();
}
};
a.m();
}
目前我的解决方案是创建一个调用super.m()
A a = new A() {
private void superMethod() {
super.m();
}
@Override
public void m() {
System.out.println("Overrided - > m()");
new Thread(new Runnable() {
@Override
public void run() {
superMethod();
}
}).start();
}
};
a.m();
我想知道为什么我无法写A.super.m()
以及是否有其他方式来执行此任务。
答案 0 :(得分:11)
我想知道为什么我无法写
A.super.m()
...
这是因为A
实际上不是直接封闭的类。 Runnable
的直接封闭类是new A() { ... }
,它是A
的匿名子类。
换句话说,如果你有的话
class A extends Base {
new Runnable() { ... }
}
然后A.super
会起作用,但现在你已经
class <Anonymous subclass of A> extends A {
new Runnable() { ... }
}
这意味着像A.super
这样的东西是不可能的,因为<Anonymous subclass of A>.super.m
没有语法。
......并且,还有其他方法可以执行此任务。
在我看来,你解决它的方式是合理的。另一种方法是创建A
的本地子类(仅用于引入要在____.super.m
中使用的标识符),如下所示:
public static void main(String[] args) {
class SubA extends A {
@Override
public void m() {
System.out.println("Override - > m()");
new Thread(new Runnable() {
@Override
public void run() {
SubA.super.m();
// ^^^^ we now have a name of the directly enclosing class
}
}).start();
}
}
A a = new SubA();
a.m();
}
答案 1 :(得分:4)
编写A.super.m(),假设A有一个带m方法的超类。 但是在你的代码中,你没有指定一个超类,默认情况下,你拥有的唯一超类是Object。 但是对象类没有一个&#39; m&#39;方法,所以你不能称之为。 做这样的事情的好方法是使用设计模式,比如装饰。
答案 2 :(得分:3)
我不认为除了你已有的方式之外,还有一种更简单的方法。
问题是匿名类A
本身(不是基类A
)无法在Runnable
类中引用。当编译为自己的类文件时,匿名类表示为package.A$1
。例如,当您在线程的superMethod
内调用run
时,将执行以下字节码:
getfield mypackage/Test$1$1/this$1 Lmypackage/Test$1;
invokestatic mypackage/Test$1/access$0(Lmypackage/Test$1;)V
为了引用它的基类A
,没有对这个内部类实例的引用,因此你可以调用super.m()
表达式。