尝试创建自定义类的通用数组时出现Java强制转换错误

时间:2008-12-25 23:34:25

标签: java generics

这就是我要做的事情:

import java.lang.reflect.*;

class exampleOuter <T extends Number>
{
    private exampleInner<T>[] elements;

    public exampleOuter(Class<T> type, int size)
    {
        elements = (exampleInner<T>[]) Array.newInstance(type, size);
    }
}

有人告诉我,如果我想创建T类通用数组,我应该使用

elements = (T[]) Array.newInstance(type,size);

所以我试着将它扩展到我的自定义类并得到一个ClassCastException(Ljava.lang.Double;不能转换为L mypackagename .exampleInner;我在main中声明这个类就像这样:

exampleOuter<Double> test = new exampleOuter(Double.class,15);

我可以声明内部类很好,我也可以声明不是innerClass通用的数组,所以我想它是outerClass的构造函数中的东西。有什么想法吗?

编辑: 我明白问题是什么。当我创建一个新的数组实例时,我创建了一个双精度数组,而不是exampleInner。我认为。如果这是正确的,我需要找到一种方法来创建一个exampleInner数组,同时只将Double.class传递给函数。

编辑2: 我意识到通用数组不是类型安全的,但无论如何我必须使用它们,因为我的老师要求我们使用它们。

编辑3: 有人告诉我,要使用通用数组,我必须以这种方式分配它们,我认为这样做需要反思。编译器告诉我该类正在使用不安全或未经检查的操作,但我必须使用通用数组,这就是我所知道的。如果有更好的方法我会更改代码。

4 个答案:

答案 0 :(得分:1)

这是我提出的解决方案:

public exampleOuter(Class<T> type, int size)
{
    innerClass<T> aux = new innerClass<T>(); 
    elements = (exampleInner<T>[]) Array.newInstance(aux.getClass(), size);
}

我认为这也有用:

elements = (exampleInner<T>[]) Array.newInstance(innerClass<T>.class, size);

但它没有,可能是因为泛型在Java中的实现(类型擦除等等)。

第一种方法的问题是我被迫创建一个新对象并实例化,尽管不是真的需要它。另外,它使代码更加臃肿imo。

编辑:第二种方法无效,因为我使用的是innerClass<T>.class而不是innerClass.class。感谢您的建议,我现在就用它。

答案 1 :(得分:0)

您正在为某些特定T创建T[]类型的对象,并将其分配给类型为exampleInner<T>[]的字段,这将是一个错误。

对于T extends NumberT[]的删除类型为Number[];已删除的exampleInner<T>[]类型为exampleInner[]。但编译器警告应该表明你无论如何都做错了。

但你几乎肯定不需要反思,所以不要使用它。

答案 2 :(得分:0)

T extends Number,你试图将它转换为exampleInner,我怀疑它是在Number层次结构中的正确位置。

在没有exampleInner的情况下尝试一下。或者尝试将exampleInner作为exampleOuter构造函数的类型参数传递。

答案 3 :(得分:0)

这里没有“通用阵列创建”。数组的组件类型是“exampleInner”(好吧,它应该是exampleInner,但是数组组件类型必须是“reified types”,因此它不能存储在运行时。),这在编译时是已知的。所以你不需要传入Double.class参数。

您真正需要做的是创建一个参数化类型的数组。一种方法是创建一个原始类型的数组,并将其转换为参数化数组类型。这将允许您像往常一样使用数组,并获得泛型的好处,当你把东西拿出来时,不必投射。

从技术上讲,这是一个未经检查的强制转换,因为它理论上可能会在以后引起意外问题,因为它无法阻止您将错误类型的对象放入数组中。但是因为这是你班级中的一个私有变量,我假设你只是在你的类中操作它,如果你相信自己的代码正确使用它,那么它就可以工作。

import java.lang.reflect.*;

class exampleOuter <T extends Number>
{
    private exampleInner<T>[] elements;

    @SuppressWarnings("unchecked")
    public exampleOuter(int size)
    {
        elements = (exampleInner<T>[]) new exampleInner[size];
    }
}