为什么这段带有泛型的java代码无法编译

问题描述 投票:0回答:3

测试.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

我的问题不是如何让这段代码工作。而是为什么这段代码不能编译。上面的代码以非正统的方式使用泛型,并且还会产生编译警告。但是我仍然希望编译器有足够的信息来编译上面的代码。

java generics
3个回答
1
投票

你宣布了

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
类型的引用。


0
投票

但是我仍然希望编译器有足够的信息来编译上面的代码。

不,没有。因为你没有给编译器足够的信息。

您在代码中使用原始类型

Wrapper
,在这种情况下,编译器无法使用所有通用类型信息。因此,编译器将
ArrayList<Wrapper>
视为
ArrayList
,这就是为什么当您迭代它时,您将返回
Object
类型值而不是
Wrapper
类型。

请参阅JLS § 4.8 - 原始类型了解更多详细信息:

未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)M 的类型是以下原始类型:对应于C对应的泛型声明中其类型的擦除。

另请参阅:


0
投票

您没有输入您的

Wrapper

public static void testing (Stack<Wrapper> stack) // <-- Here

 Wrapper test = stack.pop(); // <-- or here.

而且,这就是为什么这不是通用的。您应该有

Wrapper<TYPE>
,其中
TYPE
是合适的。

© www.soinside.com 2019 - 2024. All rights reserved.