#java #generics
#java #дженерики
Вопрос:
Если у меня есть следующий код :
public static void main(String [] args) {
List <Integer> l2 = new ArrayList <Integer>();
List <?> l3 = l2;
test(l2);
test(l3);
}
public static void test(List <?> l) {
if (l instanceof List<?>)
System.out.println("true");
}
Это выведет:
true
true
Из того, что я понимаю, <?>
это reifiable type , что означает, что он имеет некоторый тип захвата (каким бы ни был этот тип), который доступен во время выполнения.
Вопросы:
a. В методе тестирования известно ли, что l2 имеет целочисленный тип (поскольку он был удален до вызова метода)? Как это перевести так, что Л (со 2) является экземпляром списка <?>?
б. Что о L3? Как это переводится?
Комментарии:
1. java не имеет проверяемых типов, поэтому метод тестирования ничего не знает, а instanceof никогда ничего не узнает об универсальных типах.
2. @jtahlborn: (и избиратель) JLS не согласен с вами .
3. к, больше думал о том, как это применимо в общем смысле к дженерикам. теперь я вижу, что это также относится к стандартным типам (которые можно использовать повторно). однако остальная часть моего утверждения остается в силе.
Ответ №1:
Я не верю <?>
, что это подтверждено. Это просто единственный способ ссылаться на обобщенный тип без использования необработанной формы ( List
) . В обоих случаях вы просто выполняете ту же операцию, что и:
if (l instanceof List)
...
Редактировать
Действительно, я только что проверил, что они генерируют абсолютно идентичный байт-код, используете ли вы List<?>
или List
в instanceof
.
Комментарии:
1. Но <?> это reifiable типа. Это единственный повторяемый тип для подстановочного знака .. вы можете проверить множество книг SCJP. Вот одна из ссылок angelikalanger.com/GenericsFAQ/FAQSections /…
2. @yap: В этой статье говорится, что
<?>
это можно проверить в том смысле, что после удаления не было потеряно никакой информации о типе списка (потому что для начала ничего не известно о параметре типа!).). Но это невозможно проверить в том смысле, что эта информация фактически доступна для объекта во время выполнения — во время выполнения вы не знаете , что это было aList<?>
, а не aList
или aList<Integer>
.3. Ответ, предоставленный Райаном Стюартом, более точен, чем ответ, предложенный Марком Питерсом. Пожалуйста, поправьте меня, если я ошибаюсь 🙂
Ответ №2:
Неограниченный подстановочный знак можно использовать только в том смысле, что информация о типе не теряется во время выполнения, потому что нет информации о типе, которую можно потерять. Что касается ваших вопросов:
a. Метод тестирования не знает, что l2 имеет целочисленный тип. Для метода тестирования это список, содержащий «что-то», и это все.
б. Нет «перевода». Это просто список неограниченного типа, передаваемый в качестве параметра методу, который принимает список неограниченного типа.