我有以下代码
public class Container<T> {
private T element;
private T[] tarray;
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public void add(T element) {
tarray[0] = element;
}
public void CreateArray(int size) {
//Can this be cleaned up better?
tarray = (T[]) new Object[size];
}
public T get() {
return tarray[0];
}
public Container(T someElement) {
this.element = someElement;
}
public Container() {
}
public static void main(String[] args) {
Container<String> myContaier1 = new Container<String>();
myContaier1.setElement("Hello");
myContaier1.CreateArray(1);
myContaier1.add("GoodBye");
System.out.println(myContaier1.get());
}
}
是否无法初始化类型安全通用数组?
答案 0 :(得分:6)
除非您以实际T
对象的形式提供具体化的Class<T>
,否则无法表示T
的特定值。这是因为数组类型是,而通用类型不是。
答案 1 :(得分:1)
这里有两个问题:
首先,数组的实际类型始终为Object[]
。您将其投放到T[]
,但这只是因为T[]
删除到Object[]
。如果您的班级定义例如<T extends Number>
,那么(T[])new Object[]
将会失败ClassCastException
。
你可以通过将Class<T>
传递给集合的构造函数并将其保存在字段中来解决这个问题:
private Class<T> componentClass;
...
tarray = (T[]) Array.newInstance(componentClass, size);
现在tarray
的实际内存中类型为T[]
,但您仍然会收到未经检查的强制转换错误。即使你有组件类,据我所知,对于数组实例的检查强制转换没有等效的Class.cast()
。
答案 2 :(得分:-1)
您可以执行private T[] tarray;
,但无法将其分配给(T[]) new Object[size];
。 Object数组如何与任何其他类的数组相同。
编译后T
甚至不存在。
它被称为类型擦除。例如,如果你这样做
List<Person> persons = new ArrayList<Person>();
编译后变为List persons = new ArrayList()
。
答案 3 :(得分:-1)
类似于询问“有没有办法初始化通用对象:new T()
?”
当然这是不可能的,因为编译器不知道它的类型是什么。
数组是相同的,它的类型依赖于它的元素。如果其元素的类型未知,则其类型本身是未知的。
那些可以采用List
,Set
,Map
等通用类型的类是不同的。它们有自己的类作为类型,它们是动态的,因此您可以初始化类似new ArrayList<T>()
。
你可以试试这个:
public class Test {
public static void main (String args[]) {
int[] i = new int[3];
short[] s = new short[4];
ArrayList<String> a = new ArrayList<String>();
System.out.println(i.getClass().getName());
System.out.println(s.getClass().getName());
System.out.println(args.getClass().getName());
System.out.println(a.getClass().getName());
}
}
您将看到元素的类型已经与数组结合,但未与ArrayList结合使用。
答案 4 :(得分:-1)
有一种方法可以在JVM上执行此操作,但要在Java中执行此类操作需要编写大量的样板代码。在Scala中,您可以使用清单来绕过类型擦除,并且可以在不进行转换的情况下实例化通用数组。
一个例子:
class Container[T : Manifest]() {
def createArray(size:Int) = Array.ofDim[T](size)
}
scala> val f = new Container[String]
f: Container[String] = Container@12f3aa66
scala> f.createArray(5)
res7: Array[String] = Array(null, null, null, null, null)
Scala代码编译为与Java相同的字节码类文件(暗示如果你跳过足够的箍并且可能编写自己的清单,这在Java中应该是可能的)。 Scala类可以导入到Java项目中......虽然我不确定用Java实例化这样的类有多难。
如果您经常发现自己希望能够处理更复杂的类型情况,请查看Scala,您可能会喜欢它。