Java 对象重载
Java overloading with objects
我想知道为什么第二个print语句会产生"one implementation"作为输出,下面是java代码
class Point {
public boolean equals(final Object anObject) {
System.out.println("One implementation.");
return false;
}
public boolean equals(final Point aPoint) {
System.out.println("Another implementation.");
return false;
}
}
public class Main {
public static void main(final String[] args) {
final Point p1 = new Point();
final Point p2 = new Point();
final Object o = p1;
System.out.println(p1.equals(p2));
System.out.println(o.equals(p2));
System.out.println(p1.equals(o));
}
}
输出:-
另一个实现
错误
一次实现{关注}
错误
一个实现
错误
方法
boolean equals(Object other);
重载基本对象方法;这个方法
boolean equals(Point other);
没有。因此,当您调用 Object.equals()
时,这就是您在第二种情况下所做的,您最终将进入您提供的第一个实现。覆盖 Object.equals()
是您至少需要做的;其他实现是可选的,在我看来,容易误导。
应该用 @Override
注释覆盖;这可能有助于避免混淆所谓的覆盖是否真的存在。
您可以使用带有 -c -v
标志的 javap
实用程序来更好地理解正在发生的事情,完整命令 javap -c -v Main
,它的输出(我 t运行 对其进行了分类)是
public static void main(java.lang.String[]);
Code:
0: new #2 // class Main$Point
3: dup
4: invokespecial #3 // Method Main$Point."<init>":()V
7: astore_1
8: new #2 // class Main$Point
11: dup
12: invokespecial #3 // Method Main$Point."<init>":()V
15: astore_2
16: aload_1
17: astore_3
18: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
21: aload_1
22: aload_2
23: invokevirtual #5 // Method Main$Point.equals:(LMain$Point;)Z
26: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
29: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
32: aload_3
33: aload_2
34: invokevirtual #7 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
37: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
40: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
43: aload_1
44: aload_3
45: invokevirtual #8 // Method Main$Point.equals:(Ljava/lang/Object;)Z
48: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
51: return
换句话说,Java 编译器将第二次调用翻译成 java/lang/Object.equals
,因为 o
变量的类型是 Object
。 Java 是静态类型语言,因此所有类型解析都发生在编译时,因此变量 o
是否会在 运行 时间
分配 Point
无关紧要
我想知道为什么第二个print语句会产生"one implementation"作为输出,下面是java代码
class Point {
public boolean equals(final Object anObject) {
System.out.println("One implementation.");
return false;
}
public boolean equals(final Point aPoint) {
System.out.println("Another implementation.");
return false;
}
}
public class Main {
public static void main(final String[] args) {
final Point p1 = new Point();
final Point p2 = new Point();
final Object o = p1;
System.out.println(p1.equals(p2));
System.out.println(o.equals(p2));
System.out.println(p1.equals(o));
}
}
输出:-
另一个实现
错误
一次实现{关注}
错误
一个实现
错误
方法
boolean equals(Object other);
重载基本对象方法;这个方法
boolean equals(Point other);
没有。因此,当您调用 Object.equals()
时,这就是您在第二种情况下所做的,您最终将进入您提供的第一个实现。覆盖 Object.equals()
是您至少需要做的;其他实现是可选的,在我看来,容易误导。
应该用 @Override
注释覆盖;这可能有助于避免混淆所谓的覆盖是否真的存在。
您可以使用带有 -c -v
标志的 javap
实用程序来更好地理解正在发生的事情,完整命令 javap -c -v Main
,它的输出(我 t运行 对其进行了分类)是
public static void main(java.lang.String[]);
Code:
0: new #2 // class Main$Point
3: dup
4: invokespecial #3 // Method Main$Point."<init>":()V
7: astore_1
8: new #2 // class Main$Point
11: dup
12: invokespecial #3 // Method Main$Point."<init>":()V
15: astore_2
16: aload_1
17: astore_3
18: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
21: aload_1
22: aload_2
23: invokevirtual #5 // Method Main$Point.equals:(LMain$Point;)Z
26: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
29: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
32: aload_3
33: aload_2
34: invokevirtual #7 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
37: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
40: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
43: aload_1
44: aload_3
45: invokevirtual #8 // Method Main$Point.equals:(Ljava/lang/Object;)Z
48: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
51: return
换句话说,Java 编译器将第二次调用翻译成 java/lang/Object.equals
,因为 o
变量的类型是 Object
。 Java 是静态类型语言,因此所有类型解析都发生在编译时,因此变量 o
是否会在 运行 时间
Point
无关紧要