Java不允许我们这么做的原因是什么

private T[] elements = new T[initialCapacity];

我可以理解。net不允许我们这样做,因为在。net中,值类型在运行时可以有不同的大小,但在Java中,所有类型的T都将是对象引用,因此具有相同的大小(如果我错了请纠正我)。

原因是什么?


当前回答

在我的例子中,我只是想要一个堆栈数组,就像这样:

Stack<SomeType>[] stacks = new Stack<SomeType>[2];

由于这是不可能的,我使用了以下作为解决方案:

创建一个非泛型包装器类围绕堆栈(例如MyStack) MyStack[] stacks = new MyStack[2]工作得很好

丑陋,但Java是快乐的。

注意:正如BrainSlugs83在问题的评论中提到的,在.NET中完全可以有泛型数组

其他回答

如果我们不能实例化泛型数组,为什么语言有泛型数组类型?没有对象的类型有什么意义呢?

我能想到的唯一原因是varargs - foo(T…)。否则,它们可以完全删除泛型数组类型。(好吧,他们真的不需要为可变参数使用数组,因为在1.5之前不存在可变参数。这可能是另一个错误。)

所以这是一个谎言,你可以实例化泛型数组,通过varargs!

当然,泛型数组的问题仍然存在,例如。

static <T> T[] foo(T... args){
    return args;
}
static <T> T[] foo2(T a1, T a2){
    return foo(a1, a2);
}

public static void main(String[] args){
    String[] x2 = foo2("a", "b"); // heap pollution!
}

我们可以用这个例子来实际演示泛型数组的危险。

另一方面,我们已经使用泛型变参数10年了,现在还没有崩溃。所以我们可以说问题被夸大了;这没什么大不了的。如果允许显式的泛型数组创建,我们会到处都有bug;但我们已经习惯了擦除的问题,我们可以接受它。

我们可以用foo2来反驳这种说法,即规范让我们避免了他们声称让我们避免的问题。如果Sun在1.5上有更多的时间和资源,我相信他们可以达成一个更令人满意的解决方案。

试试这个:

List<?>[] arrayOfLists = new List<?>[4];

类可以声明类型为T[]的数组,但它不能直接实例化这样的数组。相反,一种常见的方法是实例化一个Object[]类型的数组,然后对类型T[]进行窄化转换,如下所示:

  public class Portfolio<T> {
  T[] data;
 public Portfolio(int capacity) {
   data = new T[capacity];                 // illegal; compiler error
   data = (T[]) new Object[capacity];      // legal, but compiler warning
 }
 public T get(int index) { return data[index]; }
 public void set(int index, T element) { data[index] = element; }
}

T vals [];/ /好吧

但是,你不能实例化T的数组 // vals = new T[10];//不能创建T的数组

你不能创建T的数组的原因是没有办法 编译器来了解实际创建的数组类型。

在我的例子中,我只是想要一个堆栈数组,就像这样:

Stack<SomeType>[] stacks = new Stack<SomeType>[2];

由于这是不可能的,我使用了以下作为解决方案:

创建一个非泛型包装器类围绕堆栈(例如MyStack) MyStack[] stacks = new MyStack[2]工作得很好

丑陋,但Java是快乐的。

注意:正如BrainSlugs83在问题的评论中提到的,在.NET中完全可以有泛型数组