Java通用数组类型转换失败?

时间:2015-03-25 06:06:49

标签: java generics

我在Java中意识到要做通用数组,这就是"一些"人们这样做(因为它在某些情况下有效):

How to create a generic array?

那些答案(或其他在线答案)一般说有两种方法可以做到,一种是对Object []进行类型转换,另一种是使用Arrsy.newInstance(),反射,但反射需要导入Java .reflect ..等我现在可能做不到的(出于限制原因)。

MyType[] newArray = (MyType[]) new Object[size];

但是,我在运行时遇到错误:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LMyClass$MyType;

如您所见,MyType是MyClass中定义的私有类。此外,MyClass定义为:

class MyClass<K,V> {
    private class MyType {
       public K data;
       public V data;
    }
    pass;
}

我猜投降失败是因为: 1,嵌套类定义 2,嵌套定义中的泛型类型?

有没有人能够解决这个问题? THX

3 个答案:

答案 0 :(得分:1)

这是人们的行为。人们做的是:

public <T> T[] createArray(Class<T> clazz , int capacity){
     return (T[]) Array.newInstance(clazz , capacity);
}

你创建一个对象数组,期望java接受它作为T的数组。这显然不起作用(出于某种原因)。基本上演员(T[]) new Object[]就好像我给你披萨并告诉你把它用作电视遥控器。如果这样可行,这将是可能的:

Object[] objArr = new Object[2];
objArr[0] = "abc";
objArr[1] = 23;

//lets assume the cast works.
String[] strArr = (String[]) objArr;
//what to do here? objArr[1] should be String, but
//is Integer -> no charAt
System.out.println(objArr[1].charAt(0));

答案 1 :(得分:1)

你只是误解了: 在子句MyType[] newArray = (MyType[]) new Object[size];中,MyType不表示类标识符,而是表示类型参数,它将被声明为此YourClass<YourType>。通用数组创建是这样的:

new K[length];
new V[length];

这是java中不允许的(允许通用数组声明(K[] genericArray))。所以你需要用

来克服这个限制
K[] genericArray = (K[]) new Object[length];

这将导致编译器的警告。使用@SuppressWarning("unchecked")来摆脱它。

这不太安全,所以不要让它暴露给客户端代码。

尽可能使用Paul的答案,因为它更安全。 (原因在于How to create a generic array in Java?)。仅当您无法获取或确定要创建的数组元素的运行时类时,才使用上面提到的不安全解决方案。例如,在参数化类的定义中,您无法获取type参数的运行时类,该类参数仅在编译期间起作用并且在此之后将被删除(类似E.class的内容将无法编译),您有使用不安全的解决方法。

答案 2 :(得分:0)

使用new创建数组时,组件类型必须是可重新类型。 MyTypeMyClass的非静态内部类,因此当您在MyType内编写MyClass而没有任何限定时,它隐含地表示MyClass<K,V>.MyType,参数化类型

通常,在这种创建参数化类型数组的情况下(注意:这与创建类型参数类型数组的问题非常不同; MyType不是类型参数),人们会创建一个原始类型或通配符参数化类型的数组(两者都是可恢复的),并转换为参数化类型的数组类型:

MyType[] newArray = new MyClass.MyType[size];

(请注意,原始类型不只是MyType,正如我们上面提到的那样MyClass<K,V>.MyType。要获取原始类型,我们必须使用原始MyClass明确限定它。 )

MyType[] newArray = (MyType[])new MyClass<?>.MyType[size];