为什么 Java 编译器抱怨使用原始类型的 foreach? [英] Why does the Java Compiler complain on using foreach with a raw type?
问题描述
在 Java 的 for-each 循环中使用泛型时,我遇到了一个奇怪的编译器错误.这是 Java 编译器的错误,还是我真的在这里遗漏了什么?
I got a strange compiler error when using generics within a for-each loop in Java. Is this a Java compiler bug, or am I really missing something here?
这是我的全班:
public class Generics<T extends Object> {
public Generics(T myObject){
// I didn't really need myObject
}
public List<String> getList(){
List<String> list = new ArrayList<String>();
list.add("w00t StackOverflow");
return list;
}
public static void main(String...a){
Generics generics = new Generics(new Object());
for(String s : generics.getList()){
System.out.println(s);
}
}
}
编译器抱怨带有 for-each 的行:类型不匹配无法从元素类型 Object 转换为 String."
如果我进行这个细微的更改,它会编译:
The compiler is complaining about the line with the for-each: "Type mismatch cannot convert from element type Object to String."
If I make this subtle change, it compiles:
public static void main(String...a){
Generics<?> generics = new Generics(new Object());
for(String s : generics.getList()){
System.out.println(s);
}
}
我知道 getList()
确实使用泛型,但它以我认为完全不相关的方式使用它们.如果我试图迭代 T 类型的内容并且 getList()
返回一个 List
或其他内容,我可以理解这一点,但这里的情况并非如此.getList()
的返回类型应该与 T 完全无关,并且不应该关心我是否为泛型对象使用原始类型......对吗?这些不应该是完全无关的,还是我真的在这里遗漏了什么?
I know getList()
does use generics, but it uses them in what I thought was a completely unrelated way. I could understand this if I were trying to iterate over something of type T and getList()
returned a List<T>
or something, but that's not the case here. The return type of getList()
should have absolutely nothing to do with T and shouldn't care whether I use the raw type for my Generics object or not...right? Shouldn't these be completely unrelated, or am I really missing something here?
请注意,如果我这样做,代码也会编译,我认为这也应该与第一个相同:
Note that the code also compiles if I do this, which I thought should have been equivalent to the first as well:
public static void main(String...a){
Generics generics = new Generics(new Object());
List<String> list = generics.getList();
for(String s : list){
System.out.println(s);
}
}
推荐答案
不同的是,当你使用原始类型时,所有成员签名中的泛型引用也被转换为它们的原始形式.如此有效地调用了一个现在具有如下签名的方法:
The difference is that when you use the raw type, all the generic references within the member signatures are converted to their raw forms too. So effectively you're calling a method which now has a signature like this:
List getList()
现在至于为什么你的最终版本会编译——虽然它会编译,但如果你使用 -Xlint
会有一个警告:
Now as for why your final version compiles - although it does, there's a warning if you use -Xlint
:
Generics.java:16: warning: [unchecked] unchecked conversion
List<String> list = generics.getList();
^
这类似于:
List list = new ArrayList();
List<String> strings = list;
... 也可以编译,但在 -Xlint
下有警告.
... which also compiles, but with a warning under -Xlint
.
故事的寓意:不要使用原始类型!
The moral of the story: don't use raw types!
这篇关于为什么 Java 编译器抱怨使用原始类型的 foreach?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!