Перегрузка Java объектами - PullRequest
1 голос
/ 13 марта 2019

Я хочу знать, почему второй оператор печати выдает «одну реализацию» как и вывод, ниже приведен код 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));
    }
}

Выход: -

Еще одна реализация

ложь

Одна реализация {беспокойство}

1012 * ложь *

Одна реализация

ложь

Ответы [ 2 ]

2 голосов
/ 13 марта 2019

Метод

boolean equals(Object other);

перегружает метод базового объекта;этот метод

boolean equals(Point other);

не имеет.Поэтому, когда вы вызываете Object.equals(), что вы делаете во втором случае, вы окажетесь в первой предоставленной вами реализации.Переопределение Object.equals() - это то, что вам нужно сделать как минимум;другие реализации являются необязательными, и, на мой взгляд, могут вводить в заблуждение.

Следует аннотировать переопределения с помощью @Override;это может помочь избежать путаницы в том, действительно ли это подразумеваемое переопределение.

1 голос
/ 13 марта 2019

Вы можете использовать утилиту 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 перевел 2-й вызов в java/lang/Object.equals, поскольку тип переменной o равен Object. Java является статически типизированным языком, поэтому все разрешения типов происходят во время компиляции, поэтому не имеет значения, будет ли переменная o назначена Point во время выполнения

...