Понимание типа стирания в Java - PullRequest
1 голос
/ 23 мая 2019

Как можно реализовать дженерики без типа стирания ?Насколько я понимаю, если у меня class Foo<T>, то T заменяется в основном заменой на Object, а у компилятора есть только метаданные, которые помогают преобразовать его в правильный параметризованный тип.

Но, еслиРеализация была реализована, тогда T будет фактическим параметризованным типом (в отличие от Object) ... Но я не понимаю, как компилятор мог бы тогда выяснить, является ли new T() допустимым вызовом (т. е. Tможет не иметь конструктора без аргументов).

1 Ответ

2 голосов
/ 24 мая 2019

В частности, в Java конструкторы не наследуются подклассами, поэтому до тех пор, пока заданный параметризованный тип T не может быть сужен до определенного типа, вы не сможете запускать new T(), поскольку Javaтипизирован независимо от того, происходит ли повторение .Однако создание экземпляра с использованием new - это только один случай , где используются классы.

Instanceof

Наиболее очевидное использование для меня дженериков, которые не были стерты, - этовозможность использовать T в выражении instanceof:

class Box<T> {
   public boolean isInst(Object obj) {
      return obj instanceof T;
   }
}

Существует также идея увидеть, является ли T суперклассом или подклассом других классов, или проверить равенство с классами.

Статические методы

С помощью reification Java сможет вызывать static методы для T «правильно».Допустим, у нас есть следующие классы:

class Parent {
   void doSomething() { System.out.println("Parent"); }
}

class Child extends Parent {
   void doSomething() { System.out.println("Child"); }
}

После того, как они определены, тогда следующий код ...

class Box<T extends Parent> {

   void test() { T.doSomething(); }

   public static void main(String...args) {
      Box<Parent> parentBox = new Box<>();
      Box<Child> childBox = new Box<>();

      parentBox.test();
      childBox.test();
   }
}

... должен вывести:

Parent
Child

, но вместо этого печатает:

Parent
Parent

Это потому, что T превращается в Parent стиранием.

Наследование

Общее наследование (как бы странно это не звучало)) может (вероятно) существовать:

public class GenericType<T> {
   public class Inner extends T {   }

   public static void main(String...args) {
      GenericType<MyClass>.Inner obj = new GenericType<MyClass>().new Inner();
      System.out.println(obj instanceof MyClass); // Prints true
   }
}
...