【问题标题】:Declaring a method when creating an object创建对象时声明方法
【发布时间】:2019-05-26 09:43:14
【问题描述】:

为什么第一种方式正确,而第二种方式不正确?


第一种方式:

new Object() {
    public void a() {
        /*code*/
    }
}.a();

第二种方式:

Object object = new Object() {
    public void a() {
        /*code*/
    }
};

object.a();

我在哪里可以找到有关它的更多信息?

【问题讨论】:

    标签: java object methods anonymous-class anonymous-inner-class


    【解决方案1】:

    在第二个选项中,您将新对象分配给Object 类型的引用。因此,只能在该引用上调用 java.lang.Object 中定义的方法。

    在第一个选项中,您基本上创建了扩展java.lang.Object 的匿名类的新对象。该匿名类具有附加方法a(),这就是您可以调用它的原因。

    【讨论】:

      【解决方案2】:

      java.lang.Object 没有声明 a 方法 (2),而 the class instance creation expression 返回的匿名类 new Object() { public void a() {} } 声明 (1)。

      使用 Java 10 的 local variable type inference (var) 使第二个选项与第一个选项一样有效。

      var object = new Object() {
          public void a() {}
      };
      object.a();
      

      【讨论】:

      • 请注意,var 是在 Java 10 中引入的,在较低版本中将不可用。
      • @ernest_k 这真的没有那么难或有趣。通过说Object object = ,您正在向下转换为Objectvarobject 提供了定义a() 的实际正确类型。
      • @SombreroChicken 我在这里了解var 的作用。但是除了问题中的第一个语法之外,没有其他方法(我知道)可以对匿名类型进行静态引用。现在我知道var 可以用于此目的。更重要的是,它允许从匿名类进行多个方法调用。我觉得这很奇怪而且很有趣!
      • 您还可以声明一个具有a() 方法的接口,并从that 创建一个匿名对象,而不是Object,这将在不支持的较低版本中工作支持var。例如,private interface HasA { public void a(); } 然后是 HasA object = new HasA() { public void a() { ... } };
      • @AndrewTobilko 是的,但是没有内联实现。我推测他们内联它是有原因的。当然,针对不同用途的不同选项。
      【解决方案3】:

      Java 是静态类型的。当您说object.a() 时,它正在寻找不存在的Object 类中的a 方法。因此它无法编译。

      你可以通过反射得到object的方法,如下所示:

      Object object = new Object() {
        public void a() {
           System.out.println("In a");
        }
      }
      
      Method method = object.getClass().getDeclaredMethod("a");
      method.invoke(object, null);
      

      这会打印出来

      在一个

      【讨论】:

      • 这不是真的。 Java 使用静态类型(您可以在示例中看到它 - Object object - 您刚刚声明了它的类型!)。它使用多态性来确定应该调用哪个方法,但这与动态类型不同。可以找到关于动态与静态的一些争论here
      • 你应该已经指出通过反射调用方法是 OP 想要的最后一件事:)
      • @MatthewRock 然而,JVM 确实支持动态调度。
      • @SolomonUcko JVM 不是 Java。动态调度也不是使语言成为静态语言的东西。 C++ 对虚拟方法具有动态调度,但仍然是一种静态语言。
      【解决方案4】:

      别担心,你需要做一些更正 两者都是访问类的私有成员的方法。通过使用第一种方式,您不必预先声明 method.ex:-

      public class demo {
      
          public static void main(String[] args) {
          new Object() {
              public void a() {
                  /*code*/
                  System.out.println("Hello");
              }
          }.a();
      
      }
      
      }
      

      但是通过使用第二种方式,您必须显式声明方法 a();在抽象类或接口中,您可以覆盖它。喜欢:-

      interface Object
      {
      public void a();
      }
      class demo {
      
      public static void main(String[] args) {
          Object object = new Object() {
              public void a() {
                  System.out.println("Hello");
              }
      
          }; object.a();
      
      
      }
      
      }
      

      希望对你有所帮助。

      【讨论】:

      • “访问类的私有成员”什么是私有成员?
      猜你喜欢
      • 2023-04-09
      • 2018-04-18
      • 2015-12-02
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 2012-11-23
      • 2021-06-21
      相关资源
      最近更新 更多