无法在 Java 中的匿名内部 Class 中定义额外方法

Cannot define extra methods in an Anonymous Inner Class in Java

Anonymous Inner Class 中定义额外的方法(不覆盖超级 class 方法)时,代码可以正常编译,没有任何问题,但如果我尝试调用额外的方法,则会抛出错误.那么,当使用 anonymous inner class 扩展时,是否只能在子 class 中使用 override 方法?如果是这样,谁能解释一下为什么?

这是我的代码的样子

class SomeClass {

    public static void main(String[] args) {
        SomeOtherClass a = new SomeOtherClass() {

            @Override 
            public void methodFromSuperClass() {

                System.out.println("Method from super class!");
            }

            public void subClassMethod() {
                System.out.println("Sub class method");
            }

        };

        a.methodFromSuperClass(); //This works fine

        a.subClassMethod(); // But calling this extra method throws an error
        
    }
}

这是我遇到的错误

 SomeClass.java:20: error: cannot find symbol
      a.subClassMethod();
      ^
      symbol:   method subClassMethod()
      location: variable a of type SomeOtherClass
    1 error

你的假设是正确的。不可能以这种方式调用未覆盖的方法。 考虑一个例子,你已经声明了一个接口并用具体的 class 实例化了它,那么你仍然只能访问接口中定义的方法,而不是 class.

中定义的方法
public interface MyInterface{
  public void someMethod();
}
public class MyImpl implements MyInterface{
  //someMethod() implementation
  // ...
  // newMethod()
  public void newMethod(){
    //some implementation
  }
}
public class Main{
  public static void main(String[] args){
    MyInterface inter = new MyImpl();
    inter.someMethod(); // this call is ok
    inter.newMethod();  // this call leads to a Symbol not found Exception, 
                        // because MyInterface has no method named newMethod...
  }
}

希望现在更清楚这是什么意思了

这种情况与匿名class名字完全一样:

class SomeOtherClass {
    public void methodFromSuperClass() { }
}

class Subclass extends SomeOtherClass {
    @Override 
    public void methodFromSuperClass() {

        System.out.println("Method from super class!");
    }

    public void subClassMethod() {
        System.out.println("Sub class method");
    }    
}

你做到了:

SomeOtherClass a = new Subclass();
a.subClassMethod();

你不同意你不应该在这里打电话给 subClassMethod 吗?毕竟,编译器知道 aSomeOtherClass 类型,但不知道它是 SomeOtherClass 的哪个子 class。它不会分析您的代码那么久远以查看您是否实际为其分配了 Subclass 的实例。

匿名classes的情况基本相同。只是这一次,subclass在你的代码中没有名字,但它仍然是一个subclass,同样的道理“编译器不会分析你的代码那么早”适用。

由于匿名子class没有名字,你不能像在命名子class例子中做类似Subclass a = new Subclass();的事情,但是因为Java 10 ,你可以这样做:

var a = new SomeOtherClass() { ... };

var 让编译器为您推断变量的类型,而无需您说出类型名称。编译器会将匿名子 class 推断为 a 的类型,这将允许您执行以下操作:

a.subClassMethod();

最后,完全允许在匿名 classes 中声明额外的成员——只是很难从匿名 class 或本地范围内以外的任何地方访问它们,因为匿名 class 没有名字。声明额外的成员有时仍然有用,因为例如您可以在覆盖的方法中访问它们。