创建对象时声明方法

32

为什么第一种方式是正确的,但第二种不是呢?


第一种方式:

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

第二种方法:

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

object.a();

那我在哪里可以找到更多相关信息呢?

4个回答

44

1
请注意,var 是在 Java 10 中引入的,不会在较低版本中提供。 - nasch
5
这并不难也不是很有趣。这段话中的 Object object = 是将其向下转型为 Object,而使用 var 可以将 object 赋予其实际正确的类型,也就是定义了 a() 方法的类型。 - Hatted Rooster
2
@SombreroChicken 我理解这里 var 的作用。但除了问题中的第一种语法之外,我不知道其他方法可以获得匿名类型的静态引用(即使我知道也没有)。现在我知道 var 可以用于此目的。更有趣的是,它允许从匿名类中进行多个方法调用。我觉得这很新奇和有趣! - ernest_k
2
你也可以声明一个具有 a() 方法的接口,并从 该接口 创建一个匿名对象,而不是使用 Object,这在不支持 var 的低版本中也可以工作。例如,private interface HasA { public void a(); } 然后 HasA object = new HasA() { public void a() { ... } }; - jpmc26
1
@AndrewTobilko 是的,但这样实现就无法进行内联了。我认为他们正在进行内联处理是有原因的。当然,对于不同的用途,有不同的选项。 - jpmc26
显示剩余4条评论

22
在第二种选项中,您将新对象分配给类型为 Object 的引用。因此,只能在该引用上调用在 java.lang.Object 中定义的方法。
而在第一种选项中,您基本上创建了一个匿名类的新对象,该类扩展了java.lang.Object。该匿名类具有附加的方法a(),这就是为什么您可以调用它的原因。

2

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);

这将会打印:

在一个


2
这不是真的。Java使用静态类型(你可以在你的例子中看到 - Object object - 你刚刚声明了它的类型!)。它使用多态来确定应该调用哪个方法,但这与动态类型不同。关于动态和静态的一些争论可以在这里找到。 - MatthewRock
2
你应该指出通过反射调用方法是 OP 最不想要的事情 :) - Andrew Tobilko
@MatthewRock JVM确实支持动态分派。 - Solomon Ucko
@SolomonUcko JVM 不是 Java。动态分派也不是使一种语言成为静态语言的东西。C++ 对于虚方法有动态分派,但仍然是一种静态语言。 - MatthewRock

0

别担心,你需要做一些修正。 这两种方法都可以访问类的私有成员。使用第一种方法,你不需要预先声明该方法。例如:

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();


}

}

希望它能有所帮助。


1
访问一个类的私有成员,什么是私有成员? - Andrew Tobilko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接