测试.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);
}
}
}
错误:
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
我的问题不是如何让这段代码工作。而是为什么这段代码不能编译。上面的代码以非正统的方式使用泛型,并且还会产生编译警告。但是我仍然希望编译器有足够的信息来编译上面的代码。
你宣布了
Wrapper test = stack.pop();
您正在使用
Wrapper
作为 原始类型。因此,在编译时,所有具有通用组件的方法和字段都显示为它们的擦除。
那么
public ArrayList<Wrapper> children;
显示为
public ArrayList children;
iterator()
的ArrayList
方法声明为
public Iterator<E> iterator() {
其中
E
是 ArrayList
的类型参数。它的擦除变成
public Iterator iterator() {
Iterator#next()
方法声明为
E next();
所以它的擦除又变成了
Object next();
您隐式地(通过 for-each 循环)尝试将
Object
类型的值分配给 Wrapper
类型的引用。
但是我仍然希望编译器有足够的信息来编译上面的代码。
不,没有。因为你没有给编译器足够的信息。
您在代码中使用原始类型
Wrapper
,在这种情况下,编译器无法使用所有通用类型信息。因此,编译器将 ArrayList<Wrapper>
视为 ArrayList
,这就是为什么当您迭代它时,您将返回 Object
类型值而不是 Wrapper
类型。
请参阅JLS § 4.8 - 原始类型了解更多详细信息:
未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)M 的类型是以下原始类型:对应于C对应的泛型声明中其类型的擦除。
另请参阅:
您没有输入您的
Wrapper
,
public static void testing (Stack<Wrapper> stack) // <-- Here
或
Wrapper test = stack.pop(); // <-- or here.
而且,这就是为什么这不是通用的。您应该有
Wrapper<TYPE>
,其中 TYPE
是合适的。