[英]Why this piece of java code with generics doesn't compile
Test.java: Test.java:
import java.util.ArrayList;
import java.util.Stack;
import java.util.Iterator;
class Wrapper<T> {
public T content;
public ArrayList<Wrapper> children;
}
public class Test {
public static void testing (Stack<Wrapper> stack) {
Wrapper test = stack.pop();
Iterator<Wrapper> itr = test.children.iterator();
while (itr.hasNext()) {
Wrapper item = itr.next();
System.out.println(item.content);
}
ArrayList<Wrapper> canCompile = test.children;
for (Wrapper child : canCompile) {
System.out.println(child.content);
}
for (Wrapper child : test.children) {
System.out.println(child.content);
}
}
}
Error: 错误:
Test.java:25: error: incompatible types
for (Wrapper child : test.children) {
^
required: Wrapper
found: Object
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
My question isn't how to get this code to work. 我的问题不是如何使这个代码工作。 But rather why this code as it stands doesn't compile. 但是为什么这个代码不能编译。 The above code uses generics in a way that's unorthodox, and it also yields compilation warnings. 上面的代码以非正统的方式使用泛型,并且它还产生编译警告。 However I would still expect the compiler to have enough information to compile the above piece of code. 但是我仍然期望编译器有足够的信息来编译上面的代码。
You declared 你声明了
Wrapper test = stack.pop();
You are using Wrapper
as a raw type . 您正在使用Wrapper
作为原始类型 。 As such, at compile time, all methods and fields that have generic components appear as their erasure. 因此,在编译时,具有通用组件的所有方法和字段都显示为其擦除。
So 所以
public ArrayList<Wrapper> children;
appears as 出现为
public ArrayList children;
The iterator()
method of ArrayList
is declared as ArrayList
的iterator()
方法声明为
public Iterator<E> iterator() {
where E
is ArrayList
's type parameter. 其中E
是ArrayList
的类型参数。 Its erasure becomes 它的擦除变成了
public Iterator iterator() {
The Iterator#next()
method is declared as Iterator#next()
方法声明为
E next();
so its erasure in turn becomes 所以它的擦除反过来变成了
Object next();
You're implicitly (through the for-each loop) trying to assign a value of type Object
to a reference of type Wrapper
. 您隐式(通过for-each循环)尝试将Object
类型的值分配给Wrapper
类型的引用。
You didn't type your Wrapper
, 你没有输入你的Wrapper
,
public static void testing (Stack<Wrapper> stack) // <-- Here
or 要么
Wrapper test = stack.pop(); // <-- or here.
And, that is why that isn't generic. 而且,这就是为什么这不是通用的。 You should have Wrapper<TYPE>
where TYPE
is appropriate. 你应该有Wrapper<TYPE>
,其中TYPE
是合适的。
However I would still expect the compiler to have enough information to compile the above piece of code. 但是我仍然期望编译器有足够的信息来编译上面的代码。
No it doesn't. 不,不。 Because you didn't gave the compiler enough information. 因为你没有给编译器足够的信息。
You are using a raw type Wrapper
in your code, in which case, all the generic type information is not available to the compiler. 您在代码中使用原始类型Wrapper
,在这种情况下,编译器无法使用所有泛型类型信息。 So, the compiler sees ArrayList<Wrapper>
as just ArrayList
, and that is why when you iterate over it, you'll get back Object
type values and not Wrapper
type. 因此,编译器将ArrayList<Wrapper>
看作只是ArrayList
,这就是为什么当你迭代它时,你会得到Object
类型值而不是Wrapper
类型。
See JLS § 4.8 - Raw Types for more details: 有关更多详细信息,请参阅JLS§4.8 - 原始类型 :
The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C. 未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是对应的原始类型在对应于C的通用声明中擦除其类型
Also See: 另见:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.