由于Java泛型的实现,你不能有这样的代码:

public class GenSet<E> {
    private E a[];

    public GenSet() {
        a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
    }
}

如何在保持类型安全的同时实现这一点?

我在Java论坛上看到一个解决方案是这样的:

import java.lang.reflect.Array;

class Stack<T> {
    public Stack(Class<T> clazz, int capacity) {
        array = (T[])Array.newInstance(clazz, capacity);
    }

    private final T[] array;
}

但我真的不明白这是怎么回事。


当前回答

这在Effective Java第二版第5章(泛型)第25项中有介绍…更喜欢列表而不是数组

你的代码将会工作,尽管它会生成一个未检查的警告(你可以用下面的注释来抑制它):

@SuppressWarnings({"unchecked"})

然而,使用List而不是Array可能会更好。

在OpenJDK项目网站上有一个关于这个bug/特性的有趣讨论。

其他回答

您不需要将Class参数传递给构造函数。 试试这个。

public class GenSet<T> {

    private final T[] array;

    @SafeVarargs
    public GenSet(int capacity, T... dummy) {
        if (dummy.length > 0)
            throw new IllegalArgumentException(
              "Do not provide values for dummy argument.");
        this.array = Arrays.copyOf(dummy, capacity);
    }

    @Override
    public String toString() {
        return "GenSet of " + array.getClass().getComponentType().getName()
            + "[" + array.length + "]";
    }
}

and

GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));

结果:

GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]

根据vnportnoy的语法

GenSet<Integer> intSet[] = new GenSet[3];

创建一个空引用数组,填充为

for (int i = 0; i < 3; i++)
{
   intSet[i] = new GenSet<Integer>();
}

这是类型安全的。

这是类型安全的唯一答案

E[] a;

a = newArray(size);

@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
    return Arrays.copyOf(array, length);
}

也许与这个问题无关,但当我得到“通用数组创建”错误使用

Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];

我用@SuppressWarnings({"unchecked"})找到了以下作品(并为我工作):

 Tuple<Long, String>[] tupleArray = new Tuple[10];

虽然线程已经死了,但我还是想提请您注意这一点。

泛型用于编译时的类型检查。因此,目的是检查

进来的就是你需要的。 你所返回的就是消费者所需要的。

检查:

在编写泛型类时,不要担心类型转换警告;当你使用它的时候要担心。