Declaring a method when creating an object
为什么第一种方法正确,第二种方法不正确?
第一种方式:
1 2 3 4 5
| new Object() {
public void a () {
/*code*/
}
}. a(); |
第二种方式:
1 2 3 4 5 6 7
| Object object = new Object() {
public void a () {
/*code*/
}
};
object. a(); |
在哪里可以找到更多关于它的信息?
java.lang.Object没有声明a方法(2),类实例创建表达式new Object() { public void a() {} }返回的匿名类(1)。
使用Java 10的本地变量类型推断(EDCOX1×7)来使第二个选项与第一个选项一样有效。
1 2 3 4
| var object = new Object() {
public void a () {}
};
object. a(); |
- 有趣的是,知道var关键字改变了这里的情况…
- 注意,在10中引入了EDCOX1×0的引用,并且在较低版本中不可用。
- @欧内斯特·劳克,这真的没那么难,也没那么有趣。通过说Object object = 你是在贬低一个Object,var给Object定义了a()的实际正确类型。
- @Sombrerochicken我理解这里var的效果。但是除了问题中的第一个语法之外,没有其他方法(我知道)对匿名类型进行静态引用。现在我知道可以用var来做这个了。更重要的是,它允许一个从匿名类进行多个方法调用。我觉得这是一个新奇有趣的地方!
- 您还可以声明一个具有a()方法的接口,并从该接口创建一个匿名对象,而不是Object方法,它可以在不支持var的较低版本中工作。例如,private interface HasA { public void a(); },然后是HasA object = new HasA() { public void a() { ... } };。
- @andrewtobilko是的,但是实现不是内联的。我以为他们加入是有原因的。当然,对于不同的用途有不同的选择。
- 自从Java 8以来,就有了Ennestk。例如,Optional.of(new Object() { public void a() { /*code*/ } }) .ifPresent(object -> object.a());,它是关于定义变量而不必命名类型,另请参见lambda中的隐含匿名类型。
- @霍尔格,谢谢!既然你提到了这一点,我甚至可以想到(new Object() {public void b() {System.out.println("bbbb");}}).b();:-)——我想它甚至可以用于更旧的版本。
- @Ernest_k是的,这在早期版本中也是可能的,但是我假设你在写评论的时候就知道了,正如你提到的,新语法"允许一个从匿名类进行多个方法调用",这是直接在创建表达式上调用方法和使用lambda e之间的根本区别。Xpression或var声明。
- @霍尔格很公平。但在这个答案之前,我从来没有发生过这样的事情(一种方法或多种方法,我从来没有见过这种技巧)。你的基于Optional的方法很漂亮。我正在考虑在提交给同行评审的下一个代码中使用它。
在第二个选项中,您将新对象分配给Object类型的引用。因此,只能对该引用调用java.lang.Object中定义的方法。
在第一个选项中,您基本上创建了扩展java.lang.Object的匿名类的新对象。那个匿名类有额外的方法a(),这就是为什么可以调用它。
Java是静态类型的。当你说object.a()时,它在Object类中寻找不存在的方法a。因此它不编译。
您可以使用反射得到Object的方法,如下所示:
1 2 3 4 5 6 7 8
| Object object = new Object() {
public void a () {
System. out. println("In a");
}
}
Method method = object. getClass(). getDeclaredMethod("a");
method. invoke(object, null); |
这个会印出来的
In a
- 那不是真的。Java使用静态类型(您可以在示例中看到它——EDCOX1 OR 18)-您刚刚声明它的类型!它使用多态性来确定应该调用哪个方法,但这与动态类型不同。关于动态与静态的一些争论可以在这里找到
- 您应该指出,通过反射调用方法是操作人员最不希望的事情:)
- @然而,JVM支持动态调度。
- "SeloMoNoCo JVM不是Java"。动态分派也不是使语言成为静态分派的东西。C++对虚拟方法有动态调度,但仍然是静态语言。
- @马修洛克到底怎么了?
别担心,你得做些修正两者都是访问类的私有成员的方法。通过使用第一种方法,您不必预先声明method.ex:-
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class demo {
public static void main (String[] args ) {
new Object() {
public void a () {
/*code*/
System. out. println("Hello");
}
}. a();
}
} |
但是通过使用第二种方法,您必须在抽象类或接口中显式声明方法a();然后您可以重写它。像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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();
}
} |
我希望它能有所帮助。