Java对象重载

时间:2019-03-13 01:57:45

标签: java overloading

我想知道为什么第二个print语句会产生“一个实现”并输出,下面是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));
    }
}

输出:-

另一种实现方式

false

一个实现{关注}

false

一个实现

false

2 个答案:

答案 0 :(得分:2)

方法

boolean equals(Object other);

重载基本的Object方法;这种方法

boolean equals(Point other);

没有。因此,当您调用Object.equals()(这是第二种情况下的工作)时,您将最终到达所提供的第一个实现中。至少需要覆盖Object.equals();其他实现是可选的,我认为容易误导。

应该用@Override注释替代;这可能有助于避免对声称的覆盖是否确实存在感到困惑。

答案 1 :(得分:1)

您可以将javap实用工具与-c -v标志一起使用,以更好地了解正在发生的事情,完整命令javap -c -v Main,其输出(我将其截断)是

  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并不重要