Уточнение типа стирания и метода моста - PullRequest
1 голос
/ 21 апреля 2019

Следующий код взят из документации Oracle по обобщению -

 class Node<T> {

    public T data;

    public Node(T data) { this.data = data; }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

 class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }

     public static void main(String[] args) {
         MyNode mn = new MyNode(5);
         Node n = mn;            // A raw type - compiler throws an unchecked warning
         n.setData("Hello");
         Integer x = mn.data;  // Causes a ClassCastException to be thrown.
     }
}

Мое понимание этого кода -

Q - метод setData переопределен или перегружен?

мое понимание - поскольку MyNode расширяется Node<Integer>, значение параметра типа T установлено на Integer.

, поэтому у класса Node есть метод setData(Integer data) как T = Integer, а у класса MyNode есть метод setData(Integer data).

переопределяет , так как подпись такая же.

Q- является ли метод setData Overrided даже после стирания? Мое понимание -

после того, как мы стерли <T>, метод set становится в Node становится, setData(Object data)

и установленный метод Mynode будет - setData(Integer data), так как нет параметра типа, нечего удалять.

Но это перегрузка .

Q - мы хотели перегрузку или переопределение?

Мое понимание - по внешнему видуметоды, определенные до стирания, мы хотели переопределить .

Q - Так как добиться оверидинга после стирания?

Мое понимание - К Метод моста .например:

setData(Object data){
    setData((Integer) Data);
}

Правильно ли мое понимание?

Кроме того, class MyNode extends Node<Integer>, когда Integer передается в <T>?когда супер называется?

1 Ответ

1 голос
/ 21 апреля 2019
  1. Да, метод setData переопределен.
  2. С точки зрения пользователя, это будет выглядеть так, как будто setData(T data) переопределяется setData(Integer i), т.е.когда вы вызываете setData(42), он печатает что-то с "MyNode" , а не с "Node" .

    На уровне стертых сигнатур методов это будет достигнуто методом синтетического моста setData(Object), добавленным к MyNode, т.е. если вы декомпилируете MyNode.class с помощью javap, вы увидите два метода:

      public void setData(java.lang.Integer);
      public void setData(java.lang.Object);
    
  3. Спецификация языка говорит "переопределить" , я не знаю, почему кто-то хотел бы чего-то другого.

  4. Непонятно, что вы подразумеваете под "добиться переопределения после стирания" .Стирание типа происходит после проверки типа и определения того, что переопределяет.Нечего «достигать», это просто порядок, в котором все работает (см. Также этот комментарий ).Синтетический метод моста, который переопределяет исходный setData(Object), выглядит так, как вы написали (с небольшими опечатками):

    setData(Object data){
        setData((Integer) data);
    }
    

    по крайней мере, это то, что в документации написано .Но это синтетический метод, он генерируется компилятором автоматически.Если он появится в исходном коде, это приведет к ошибкам компиляции.

...