泛型与遗留代码的兼容性-为什么当迭代器运行良好时,foreach在运行时会受到打击

问题描述 投票:-1回答:1

我有以下测试代码。我正在尝试了解泛型和旧版之间的互操作性。

List myList = new ArrayList();
myList.add("abc");
myList.add(1);
myList.add(new Object());

System.out.println("Printing the unchecked list");
Iterator iterator = myList.iterator();
while (iterator.hasNext()) {
  System.out.println(iterator.next());
}

List<String> strings = myList;

System.out.println("Printing the unchecked list assigned to List<String> using iterator");
Iterator stringIterator = strings.iterator();
while (stringIterator.hasNext()) {
  System.out.println(stringIterator.next());  // this works fine! why? shouldn't it fail converting the 1 (int/Integer) to String?
}

System.out.println("Printing the unchecked list assigned to List<String> using for");
for (int i = 0; i != strings.size(); i++) {
  System.out.println(strings.get(i));  // blows up as expected in the second element, why?
}

System.out.println("Printing the unchecked list assigned to List<String> using foreach");
for (String s : strings) {
  System.out.println(s);  // blows up as expected in the second element, why?
}

为什么当我尝试使用iterator.next循环进行迭代时System.out.println爆炸时for不能正常工作?

java generics compatibility legacy-code
1个回答
2
投票

关于泛型要记住的关键是,它只是一种从源代码省略强制类型转换的方法。强制类型转换由编译器插入。因此,由于强制转换的存在(或不存在),代码将失败(或不会失败)。

  1. 这很好!为什么?

因为stringIterator是原始的,所以stringIterator.next()不会转换为任何东西:它只是作为Object读取,这是已删除的返回类型。

  1. 在第二个元素中爆炸,为什么?

stringsList<String>,因此strings.get(i)的结果假定为String,并且选择要调用println(String),而不是println(Object)。这样,将插入演员表。 strings.get(1)不是String,因此失败,显示ClassCastException

有趣的是,如果您一直尝试使用List<Integer>进行操作,这不会失败,因为将调用println(Object),这样就不需要强制转换了。

  1. 在第二个元素中爆炸,为什么?

因为插入了对String的强制转换,以将元素分配给String s

有关增强的for循环的简化形式,请参阅JLS 14.14.2

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.