English 中文(简体)
尝试创建自定义类的通用数组时出现Java转换错误。
原标题:
  • 时间:2008-12-25 23:34:24
  •  标签:

这就是我试图做的事情:

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;无法转换为Lmypackagename.exampleInner;我在main中声明类如下:

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

我可以正常声明内部类,也可以声明非泛型的内部类数组,因此我想问题可能出在外部类的构造函数中。有什么想法?

EDIT: I understand what the problem is. When I create a new instance of the array, I create an array of doubles, not of exampleInner. I think. If that s right, I need to find a way to create an array of exampleInner while passing just Double.class to the function.

EDIT 2: I realize generic arrays are not typesafe, but I have to use them anyway because my teacher demands that we use them.

EDIT 3: I was told that to use generic arrays I had to allocate them that way, and to do so I need reflections, I think. The compiler tells me the class is using unsafe or unchecked operations, but I have to use generic arrays and that s the way I know to do it. If there s a better way I ll change the code.

问题回答

这是我想出来的解决方案:

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 中泛型的实现方式(类型擦除等)。

第一种方法的问题在于,即使我并不真正需要它,也被迫创建一个新对象并进行实例化。此外,我认为它会使代码更加臃肿。

编辑:第二种方法没有起作用是因为我使用了innerClass<T>.class而不是innerClass.class。谢谢你的建议,我现在会使用它。

T继承Number,并尝试将其转换为exampleInner,我怀疑它是否在Number层次结构的正确位置上。

尝试不使用您的exampleInner。或者尝试将exampleInner作为类型实参传递给exampleOuter构造函数。

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

对于 T extends NumberT[] 的被擦除类型为 Number[];对于 exampleInner<T>[] 的被擦除类型为 exampleInner[]。但是编译器警告应该已经指示您正在做错误的事情。

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

你这里没有“通用数组创建”。数组的组件类型是“exampleInner”(实际上应该是exampleInner,但是数组组件类型必须是“具体化类型”,所以无法在运行时存储)。这在编译时已知。因此,你不需要传递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];
    }
}




相关问题
热门标签