How to create generic array? [duplicate]

被刻印的时光 ゝ 提交于 2019-12-10 17:32:19

问题


Possible Duplicate:
Java how to: Generic Array creation

How to create an array of type T[] in Java? I can't use Arrays.newInstance() since I have no objects of Class<T>. Is there a generic version of newInstance somewhere?

My method prototype follows:

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

   // filling answer with data

   return answer;

}

UPDATE

Sorry in example above I can take class from balls. But suppose I have no such a variable.

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

   // filling answer with data

   return answer;

}

or

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

      T[][] answer = ????

      // filling answer with data

      return answer;

   }
}

UPDATE2

This example also does not work:

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");

}

}

回答1:


1. Arrays are Not Generic

2. Thats the reason Arrays are checked during compile as well as runtime, where as Collections can be Generic and its checked only during the compile time....




回答2:


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




回答3:


What you ask is not possible. An array knows its component type at runtime, and arrays of different component types are different runtime types. That's why when you create the array, you need to know the component type at runtime.

Since your method is generic over T, the caller can dictate the T it wants to use to the compiler every time it calls this method. So consider how absurd this is:

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

The compiled code on the right side of this is identical for the two lines. The .<String> stuff is just hints to the compiler, and do not affect the compiled code. So this means that distribute() must return something that is both String[][] and Integer[][] (which is then checked at runtime, since String[][] and Integer[][] are reified runtime types). The only value that can satisfy this is null.

(You might ask, why does this problem not occur for methods that return List<T>? The answer is that, unlike for arrays, there is only one class List at runtime. And lists do not know their component types at runtime. So a new ArrayList<Foo>() and a new ArrayList<Bar>() are exactly the same at runtime. So they don't have this problem.)

Another analogy of what is happening here: So array types have an inheritance pattern that follows the inheritance of their component types. So Integer[][] is a subclass of Object[][]. And in fact, all T[][] are subclasses of Object[][]. So instead of Object[][] and its subclasses, let's consider a non-array class, MyBaseClass, which has a bunch of subclasses. Then, what you are basically asking is to be able to generically create an instance of an unknown subclass of MyBaseClass (determined by a type parameter).

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

I hope you can see why this is impossible.




回答4:


Do: T[][] answer = (T[][]) new Object[][];
T will be erased anyway by compiler to Object. Of course you need to know the size of the array.

Update:
In your new example you get the exception here:
Integer[] c = a.gen1(); // this causes ClassCastException
Because you are trying to cast an Object[] to an Integer[]. Not possible.
What you get back is an Object[] but containing Integer references. So you would need to do:

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

This is ok since n is an Integer.
But as a general rule: If you need to collect parameterized type objects, simply use an ArrayList. In your example where you don't even have the actual class to instantiate the array via reflection it is the only sensible choice



来源:https://stackoverflow.com/questions/12020527/how-to-create-generic-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!