Различия дженериков в Java и не-дженериков в Java - PullRequest
0 голосов
/ 06 августа 2020

Итак, что отличает обычный класс, метод от универсального c метода или класса, так это то, что конструктор для определения класса или метода может принимать любой тип значения аргумента для Generics? Я также читал и не уверен в этом, но как все значения аргументов Generi c в конечном итоге компилируются в один и тот же тип данных каким-то образом в этой концепции, называемой стиранием типа?

Кроме того, если бы я сделал два экземпляра, например this

Test <String> sObj = new Test<String>("GeeksForGeeks");  
Test <Integer> sObj2 = new Test<Integer>(4);  

Предполагая, что Test является классом Generi c, я понимаю, что оба являются двумя разными экземплярами класса Test, но могу ли я сказать, что это два разных типа класса Test, поскольку оба используют два разных Generi c, или можно было бы с уверенностью сказать, что они оба относятся к одному типу объектов класса Test, если они в конечном итоге компилируют одно и то же с помощью Type Erasure, я полагаю?

1 Ответ

1 голос
/ 06 августа 2020

Здесь следует учитывать два разных контекста: время компиляции и время выполнения.

Разница между классами generi c и non-generi c во время компиляции заключается в наличии одного или более общих c аргументов в сигнатуре класса или метода.

Во время компиляции Test<String> и Test<Integer> обрабатываются как разные типы. Преимущество этого заключается в том, что если вы попытаетесь использовать Test<String> где-нибудь, где ожидается Test<Integer>, компилятор пожалуется.

sObj = sObj2; // compiler complains

Это хорошо, потому что, вероятно, это была простая ошибка, который вы хотите поймать и исправить прямо сейчас.

Во время выполнения каждый объект имеет небольшие дополнительные метаданные, связанные с ним, чтобы сообщить вам, что это за тип. Это полезно по многим причинам, включая Reflection (вызов таких методов, как .getClass()) и предотвращение недопустимых приведений:

Object obj = "foo";
Integer i = (Integer) obj; // compiler doesn't complain, but an exception is thrown

Type Erasure означает, что этот дополнительный небольшой бит метаданных содержит нет информации об общих c типах во время выполнения.

if(sObj.getClass().equals(sObj2.getClass())) { // This will be true
   sObj = (Test<String>) sObj1; // this will not produce an error.
}

У этого есть некоторые недостатки. Например, в приведенном выше коде явно есть ошибка в logi c, но вместо того, чтобы увидеть недопустимое приведение в строке выше, вы, вероятно, получите недопустимое приведение в совершенно другой части кода, когда вы попробуйте преобразовать Integer в String.

Но к тому времени, когда язык Java добавил дженерики, реализация его любым другим способом имела бы множество других недостатков с точки зрения усилий и потеря обратной совместимости. Поэтому они решили использовать Type Erasure вместо Reified Generics.

См. Также: Почему меня должно волновать, что Java не имеет reified generics?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...