Ключевым моментом, который следует помнить о дженериках, является то, что это просто способ пропустить приведение из исходного кода. Приведения вставляются компилятором. Итак, код не работает (или не дает сбой) из-за наличия (или отсутствия) приведения.
- это работает отлично! почему?
Поскольку stringIterator
является необработанным, stringIterator.next()
не приводится ни к чему: он просто читается как Object
, который является стертым типом возврата.
взрывается, как и ожидалось, во втором элементе, почему?
strings
это List<String>
, поэтому результат strings.get(i)
предполагается равным String
, и println(String)
выбирается для вызова, а не println(Object)
. Таким образом, приведение вставлено. strings.get(1)
не является String
, так что это не так с ClassCastException
.
Интересно, если бы вы пробовали это с List<Integer>
, это бы не сработало, потому что println(Object)
будет вызван, и никакое приведение не будет необходимо.
взрывается, как и ожидалось, во втором элементе, почему?
Поскольку вставлено приведение к String
, чтобы присвоить элемент String s
.
Обратитесь к JLS 14.14.2 , чтобы узнать, как выглядит расширенная форма для l oop:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
{VariableModifier} TargetType Identifier =
(TargetType) #i.next();
Statement
}
Итак, ваш код эквивалентен:
for (Iterator<String> it = strings.iterator(); it.hasNext(); ) {
String s = (String) it.next(); // Actually, your code fails on this line.
System.out.println(s);
}