从覆盖方法内的匿名内部 class 调用超级方法
Calling super method from within an anonymous inner class inside the overridden method
假设我们有一个 class:
class A {
public void m() {
System.out.println("A - > m()");
}
}
...我想在 class 创建 时重写方法 m
而无需 创建第二个子 class 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()
以及是否有其他方法可以执行此任务。
写A.super.m(),假设A有一个superclass和一个m方法。
但是在您的代码中,您没有指定 superclass,默认情况下,您拥有的唯一 superclass 是 Object.
但是 Object class 没有 'm' 方法,所以你不能调用它。
做这样的事情的一个好方法是使用设计模式,比如装饰器。
除了您已有的方法,我认为没有比这更简单的方法了。
问题是匿名classA
本身(不是基础classA
)无法在Runnable
[=25]中被引用=].匿名 class 在编译到它自己的 class 文件时表示为类似 package.A
的东西。例如,当你在线程的 run
内部调用 superMethod
时,会执行以下字节码:
getfield mypackage/Test/this Lmypackage/Test;
invokestatic mypackage/Test/access[=10=](Lmypackage/Test;)V
为了引用其基础 class A
,没有引用此内部 class 实例,因此您调用 super.m()
表达式。
I want to know why I am not able to write A.super.m()
...
这是因为A
实际上不是直接包围class。 Runnable
的直接封闭 class 是 new A() { ... }
,它是 A
.
的匿名子 class
换句话说,如果你有
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
没有语法。
...and, is there another way to perform this task.
我觉得你的解决方法是合理的。另一种方法是创建 A
的本地子 class(只是引入一个标识符以在 ____.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();
}
假设我们有一个 class:
class A {
public void m() {
System.out.println("A - > m()");
}
}
...我想在 class 创建 时重写方法 m
而无需 创建第二个子 class 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()
以及是否有其他方法可以执行此任务。
写A.super.m(),假设A有一个superclass和一个m方法。
但是在您的代码中,您没有指定 superclass,默认情况下,您拥有的唯一 superclass 是 Object.
但是 Object class 没有 'm' 方法,所以你不能调用它。
做这样的事情的一个好方法是使用设计模式,比如装饰器。
除了您已有的方法,我认为没有比这更简单的方法了。
问题是匿名classA
本身(不是基础classA
)无法在Runnable
[=25]中被引用=].匿名 class 在编译到它自己的 class 文件时表示为类似 package.A
的东西。例如,当你在线程的 run
内部调用 superMethod
时,会执行以下字节码:
getfield mypackage/Test/this Lmypackage/Test;
invokestatic mypackage/Test/access[=10=](Lmypackage/Test;)V
为了引用其基础 class A
,没有引用此内部 class 实例,因此您调用 super.m()
表达式。
I want to know why I am not able to write
A.super.m()
...
这是因为A
实际上不是直接包围class。 Runnable
的直接封闭 class 是 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
没有语法。
...and, is there another way to perform this task.
我觉得你的解决方法是合理的。另一种方法是创建 A
的本地子 class(只是引入一个标识符以在 ____.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();
}