4

可能重复:
Java 如何:创建通用数组

T[]如何在 Java中创建类型数组?我不能使用Arrays.newInstance(),因为我没有Class<T>. newInstance某处有通用版本吗?

我的方法原型如下:

public <T> T[][] distribute(T ... balls) {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

更新

对不起,在上面的例子中,我可以从balls. 但是假设我没有这样的变量。

public <T> T[][] distribute() {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

或者

class<T> {
   public T[][] distribute() {

      T[][] answer = ????

      // filling answer with data

      return answer;

   }
}

更新2

此示例也不起作用:

public abstract class GenericArray<T> {

abstract public T create();

public T[] gen1() {
    T[] ans = (T[]) new Object[3];
    ans[0] = create();
    ans[1] = create();
    ans[2] = create();
    return ans;
}

public Integer[] gen2() {
    Integer[] ans = new Integer[3];
    ans[0] = new Integer(0);
    ans[1] = new Integer(0);
    ans[2] = new Integer(0);
    return ans;
}

public static void main(String[] args) {

    GenericArray<Integer> a = new GenericArray<Integer>() {

        @Override
        public Integer create() {
            return new Integer(0);
        }
    };

    Integer[] b = a.gen2();
    Integer[] c = a.gen1(); // this causes ClassCastException

    System.out.println("done");

}

}
4

4 回答 4

6

1. Arrays不是_ Generic

2.这就是在编译期间和运行时检查Arrays的原因,其中可以是Generic并且仅在编译时检查....Collections

于 2012-08-18T17:09:10.283 回答
1

(T[][]) new Object[size][size]

于 2012-08-18T17:09:57.130 回答
1

你问的是不可能的。一个数组在运行时就知道它的组件类型,不同组件类型的数组就是不同的运行时类型。这就是为什么在创建数组时,需要在运行时知道组件类型。

由于您的方法是通用的 over ,因此调用者可以在每次调用此方法时向编译器T指示它想要使用的方法。T所以想想这是多么荒谬:

String[][] foo = this.<String>distribute();
Integer[][] bar = this.<Integer>distribute();

右侧的编译代码对于这两行是相同的。这些.<String>东西只是对编译器的提示,不会影响编译的代码。所以这意味着distribute()必须返回一个既是String[][]and的东西Integer[][](然后在运行时检查它,因为String[][]andInteger[][]是具体化的运行时类型)。唯一可以满足的值是null

(你可能会问,为什么返回的方法不会出现这个问题List<T>?答案是,与数组不同,在运行时只有一个类List。而列表在运行时不知道它们的组件类型。所以 a和new ArrayList<Foo>()a正好运行时相同。所以他们没有这个问题。)new ArrayList<Bar>()

这里发生的另一个类比:因此数组类型具有遵循其组件类型继承的继承模式。Integer[][]的子类也是如此Object[][]。事实上,它们T[][]都是Object[][]. 因此Object[][],让我们考虑一个非数组类,而不是它的子类,MyBaseClass它有一堆子类。然后,您基本上要问的是能够一般地创建一个未知子类的实例MyBaseClass(由类型参数确定)。

<T extends MyBaseClass> T distribute() {
    T answer = //...?
    return answer;
}

我希望你能明白为什么这是不可能的。

于 2012-08-18T19:39:14.810 回答
0

Do:T[][] answer = (T[][]) new Object[][];
T无论如何都会被编译器擦除到Object. 当然你需要知道数组的大小。

更新:
在您的新示例中,您在此处遇到异常:
Integer[] c = a.gen1(); // this causes ClassCastException
因为您正在尝试将 anObject[]转换为Integer[]. 不可能。
你得到的是一个Object[]但包含Integer引用。所以你需要这样做:

Object[] c = a.gen1();
for(Object n:c){  
    Integer nn = (Integer) n;  
}  

这没关系,因为n它是一个Integer.
但作为一般规则:如果您需要收集参数化类型对象,只需使用ArrayList. 在您甚至没有实际class通过反射实例化数组的示例中,这是唯一明智的选择

于 2012-08-18T17:11:00.353 回答