【问题标题】:Unable to Access Anonymous Class Method in Java无法访问 Java 中的匿名类方法
【发布时间】:2015-06-12 04:42:51
【问题描述】:

每当我尝试从外部类调用属于匿名类的方法时,都会收到编译器错误。示例:

public class Test {

    public static void main(String[] args) {
        Test testObj = new Test(){
            public void doStuff(){
                System.out.println("Test");
            }
        };
        testObj.doStuff();
    }
}

编译器提供的错误只是“找不到符号 - doStuff()”。我一定是忽略了什么……有什么想法吗?

提前致谢。

【问题讨论】:

    标签: java compiler-errors anonymous-class anonymous-inner-class


    【解决方案1】:

    您只能从 Test 类的 Reference 中调用现有方法。所以如果你声明了doStuff() 方法,那么只有你可以使用Test testObj 引用来调用它。

    看到这个问题Is it possible to call subclasses' methods on a superclass object?

    但是你当然可以在匿名类的其他方法声明中调用新方法。请参见下面的示例。

    示例:

    public class Test {
        public void doStuff() {
            System.out.println("Test");
        }
    
        public static void main(String[] args) {
            Test testObj = new Test() {
                public void doStuff() {
                    System.out.println("Inside anonymous class doStuff");
                    doOtherStuff(); // calling new method doOtherStuff() and it works
                }
    
                public void doOtherStuff() {
                    System.out.println("Inside anonymous class doOtherStuff");
                }
            };
            testObj.doStuff();
    
            /*Below code give compilation error: The method doOtherStuff() is undefined for the type Test*/
            // testObj.doOtherStuff();
        }
    }
    

    输出:

    Inside anonymous class doStuff
    Inside anonymous class doOtherStuff
    

    【讨论】:

    • 我不这么认为......你总是可以在匿名类中创建新方法。只是您可能无法使用超类引用来调用它。
    • @AbishekManoharan 因此,对于匿名类,您几乎只能为它们分配超类的类型。换句话说,他们不能有自己的类型,对吗?
    • 不,他们不能...但这并不意味着新方法没有用。请参阅使用它的更新答案。
    • @Polymorph 匿名类有自己的类型,但你无法通过名称访问该类型(因此,它是匿名的)。但是可以直接访问。请参阅我对这个问题的回答。
    【解决方案2】:

    Java 是一种类型安全的语言。当你有一个 Test 类的对象(你声明 testObj 是)时,编译器将只允许你调用类 Test 中定义的方法。即使你有一个子类的实例,编译器也不会自动推断,所以它不会让你调用子类方法。它只根据变量的类型。

    您需要在Test 类中定义doStuff 方法。

    当然,这使得匿名子类化它很愚蠢,除非你想重写该方法来做其他事情。

    【讨论】:

      【解决方案3】:

      问题在于匿名类没有类型名称(这就是它被称为匿名的原因)。

      您将匿名类实例分配给Test 类型的变量,而Test 类型没有名为doStuff 的方法。

      因此,您不能将匿名类实例分配给任何变量,然后在其上调用未在超类中定义的方法。

      如果你不指定它,可以调用该方法的:

      public class Test {
      
          public static void main(String[] args) {
              new Test(){
                  public void doStuff(){
                      System.out.println("Test");
                  }
              }.doStuff();
          }
      }
      

      请注意,在现实世界的 Java 程序中,这在少数情况下很有用。

      我只是为了突出问题的根源:当然允许匿名类具有未在超类中定义的方法,而您不能轻易调用它们的唯一原因是因为类的类型是匿名的(没有名字)。但它们仍然存在,可以直接在实例上调用。

      【讨论】:

        【解决方案4】:

        问题本质上归结为,引用变量和对象之间有什么区别。 testObj 变量是Test 类型,Test 没有doStuff 方法,只有你的匿名类有,但是编译器虽然可以创建匿名类型的object,但不能创建变量 的匿名类型。底线是您不应该对这种类型的代码使用匿名类型,即子类具有不在父类中的方法的代码。相反,要么为父类提供方法(此处为 Test 提供 doStuff 方法),要么考虑使用私有内部类代替您的匿名类。

        【讨论】:

          【解决方案5】:

          Test 类没有方法 doStuff()。当您创建匿名类时,您添加了一个名为doStuff() 的新方法。然后将该引用存储为 Test 类型,这样就无法访问额外的方法。

          你为什么要使用这样的匿名类?

          最简单的方法就是添加doStuff()方法来测试

          public class Test {
          
               public void doStuff(){
                    System.out.println("Test");
               }
          
              public static void main(String[] args) {
                  Test testObj = new Test();
                  testObj.doStuff();
              }
          }
          

          【讨论】:

          • 感谢您的回复。我的示例并不实用,我知道我可以轻松地将 doStuff() 方法直接添加到 Test 类。目标是更好地掌握匿名类。所以,如果我现在正确理解这一点:如果我从父类覆盖它们,我只能在匿名类对象上运行方法?
          • @Polymorph - 不,您可以在匿名类上运行方法,只要该方法是您可以引用或强制转换的对象上的可见方法。它不必被覆盖。当然匿名类中的其他方法如果也被其他方法调用也可以执行
          猜你喜欢
          • 2016-03-15
          • 1970-01-01
          • 1970-01-01
          • 2013-09-03
          • 1970-01-01
          • 2018-10-30
          • 1970-01-01
          • 2011-02-09
          • 1970-01-01
          相关资源
          最近更新 更多