如何创建通用数组? [复制]
Posted
技术标签:
【中文标题】如何创建通用数组? [复制]【英文标题】:How to create generic array? [duplicate] 【发布时间】:2012-08-14 18:31:36 【问题描述】:可能重复:Java how to: Generic Array creation
如何在Java中创建T[]
类型的数组?我不能使用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");
【问题讨论】:
为什么你不能从balls
可变参数之一获得Class<T>
,假设有一个? if(balls.length > 0) Class<T> clazz = balls[0].getClass();
无论如何,你不可避免地会听到“数组和泛型不能很好地结合在一起”。
最简单的方法是不使用数组,使用某种Collection
。
【参考方案1】:
1. Arrays
是不是 Generic
2.这就是Arrays
在编译和运行时被检查的原因,其中Collections
可以是通用和仅在编译期间检查....
【讨论】:
那么在只有generoc信息的情况下不可能创建一个类型的数组? 你可以使用类似@SuppressWarnings("unchecked") B<Integer>[] arr = new B[3];
的东西,但你需要禁止编译器警告....但是为什么在运行时不存在通用信息时这样做,而且我不喜欢使用我在java中工作时的数组。集合提供了更大的灵活性
是的。或者,更准确地说:您没有泛型信息开始,因为它在运行时被删除(至少在纯 java 中)。这是一个编译时特性,一旦你的应用程序运行就完全失去了。
@sarcan ya...该过程称为Erasure
,其中compiler removes the Type Parameter and Argument Parameters from the class , method, etc..
。使其成为原始类型(原始类型是没有类型参数的泛型类或接口名称【参考方案2】:
(T[][]) new Object[size][size]
【讨论】:
【参考方案3】:你问的是不可能的。数组在运行时知道它的组件类型,不同组件类型的数组是不同的运行时类型。这就是为什么在创建数组时,需要在运行时知道组件类型。
由于您的方法对T
是通用的,因此调用者可以在每次调用此方法时向编译器指示它想要使用的T
。所以想想这是多么荒谬:
String[][] foo = this.<String>distribute();
Integer[][] bar = this.<Integer>distribute();
右侧的编译代码对于这两行是相同的。 .<String>
只是对编译器的提示,不会影响编译后的代码。所以这意味着distribute()
必须返回String[][]
和Integer[][]
的东西(然后在运行时检查,因为String[][]
和Integer[][]
是具体化的运行时类型)。唯一可以满足这一点的值是null
。
(你可能会问,为什么返回List<T>
的方法不会出现这个问题?答案是,与数组不同,在运行时只有一个类List
。并且列表不知道它们的组件类型在运行时。所以 new ArrayList<Foo>()
和 new ArrayList<Bar>()
在运行时完全相同。所以它们没有这个问题。)
这里发生的另一个类比:因此数组类型具有遵循其组件类型继承的继承模式。所以Integer[][]
是Object[][]
的子类。事实上,所有T[][]
都是Object[][]
的子类。因此,让我们考虑一个非数组类MyBaseClass
,而不是Object[][]
及其子类,它有一堆子类。然后,您基本上要问的是能够一般地创建MyBaseClass
的未知子类的实例(由类型参数确定)。
<T extends MyBaseClass> T distribute()
T answer = //...?
return answer;
我希望你能明白为什么这是不可能的。
【讨论】:
【参考方案4】:执行:T[][] answer = (T[][]) new Object[][];
T
无论如何都会被编译器擦除为Object
。当然你需要知道数组的大小。
更新:
在您的新示例中,您会在此处遇到异常:Integer[] c = a.gen1(); // this causes ClassCastException
因为您试图将Object[]
转换为Integer[]
。不可能。
你得到的是一个Object[]
,但包含Integer
引用。所以你需要这样做:
Object[] c = a.gen1();
for(Object n:c)
Integer nn = (Integer) n;
这没关系,因为n
是Integer
。
但作为一般规则:如果您需要收集参数化类型对象,只需使用ArrayList
。在您的示例中,您甚至没有实际的 class
来通过反射实例化数组,这是唯一明智的选择
【讨论】:
这不会在运行时导致ClassCastException
吗?
否,因为类型参数T
将被编译器删除,并且无论如何都会被Object
替换。这称为type-erasure
。您正在将特定对象添加到@ 987654338@数组是合法的
@Dims 仅当您尝试将其分配给T
的具体类型时才会导致ClassCastException
:String[] foo = foo(); public static <T> T[] foo() return (T[]) new Object[5];
@Jeffrey @user384796 我试过了,它导致了ClassCastException
。我需要创建普通类型的普通数组。以上是关于如何创建通用数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章