从覆盖方法内的匿名内部 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();
}