使用泛型方法时抛出类抛出异常

时间:2012-09-28 12:55:42

标签: java arrays exception generics classcastexception

所以,我正在使用2D数组作为我正在研究的平台物理系统。不幸的是,由于各种原因,2D阵列需要通用类型。

我正在用一些java Collections(精确的链表)动态构建表面,然后用一些hacky trickery将它们转换为2D数组。这当前有效,给我适当的2D通用数组:*

LinkedList<PhysSurface<P>> leftSurfaces = new LinkedList<PhysSurface<P>>();
LinkedList<PhysSurface<P>> rightSurfaces = new LinkedList<PhysSurface<P>>();
LinkedList<PhysSurface<P>> topSurfaces = new LinkedList<PhysSurface<P>>();
LinkedList<PhysSurface<P>> bottomSurfaces = new LinkedList<PhysSurface<P>>();

// Add surfaces to the lists

GenericArray<PhysSurface<P>[]> base = new GenericArray<PhysSurface<P>[]>(4);
PhysSurface<P>[][] surfaces = base.elements();
surfaces[0] = leftSurfaces.toArray(new GenericArray<PhysSurface<P>>().elements());
surfaces[1] = rightSurfaces.toArray(new GenericArray<PhysSurface<P>>().elements());
surfaces[2] = topSurfaces.toArray(new GenericArray<PhysSurface<P>>().elements());
surfaces[3] = bottomSurfaces.toArray(new GenericArray<PhysSurface<P>>().elements());

但是,当我尝试将这一切都放入这样的通用静态方法时:

@SuppressWarnings("unchecked")
public static <T> T[][] to2DArray(Collection<T>... collections)
{
    GenericArray<T[]> base = new GenericArray<T[]>(collections.length);
    T[][] array = base.elements();
    for(int i = 0; i < collections.length; i++)
        array[i] = collections[i].toArray(new GenericArray<T>().elements());
    return array;
}

然后我调用这样的方法:

PhysSurface<P>[][] surfaces = GenericsUtils.to2DArray(leftSurfaces, rightSurfaces, topSurfaces, bottomSurfaces);

然后一切崩溃,给我一个ClassCastException,说它不能将类型Object转换为类型PhysSurface。堆栈跟踪在这里:

Exception in thread "main" java.lang.ClassCastException: [[Ljava.lang.Object; cannot be cast to [[Lcom.meg.utils._2D.platformer.phys.environment.surface.PhysSurface;
    at com.meg.chaos_temple.test.world.PhysTestWorld$TestMap.<init>(PhysTestWorld.java:487)
    at com.meg.chaos_temple.test.world.PhysTestWorld$TestPlayer.<init>(PhysTestWorld.java:245)
    at com.meg.chaos_temple.test.world.PhysTestWorld.<init>(PhysTestWorld.java:95)
    at com.meg.chaos_temple.main.ChaosDebug.createWorld(ChaosDebug.java:72)
    at com.meg.jrabbit.engine.main.BaseGame.start(BaseGame.java:56)
    at com.meg.jrabbit.engine.loop.Loop.run(Loop.java:44)
    at com.meg.jrabbit.engine.main.BaseGame.run(BaseGame.java:40)
    at com.meg.jrabbit.engine.main.StandardGame.run(StandardGame.java:85)
    at com.meg.chaos_temple.main.ChaosDebug.main(ChaosDebug.java:19)

据我所知,泛型方法不是使用泛型类型T,而是默认创建一个Object [] []并在返回时尝试强制转换。如果这是正在发生的事情,为什么这在放入静态方法时不起作用?如果没有,那到底是怎么回事?


  • (GenericArray是一个自定义类,它使用可变长度参数来绕过制作泛型数组的常规障碍,然后包装结果。实际构造函数是GenericArray(T ...元素)。)

1 个答案:

答案 0 :(得分:3)

不幸的是,T[][] array在运行时与Object[][] array相同。通用类型参数将在运行时删除;只有编译器知道它。

解决方案是传递对象的类:Class<T>

import java.reflect.Array;

...

public static <T> T[][] to2DArray(Class<T> klazz, Collection<T>... collections)
{
    T[][] array = (T[][]) Array.newInstance(klazz, collections.length,
                                                   collections[0].size());
    //...
        array[i] = (T[]) Array.newInstance(klazz, collections[i].size());
    return array;
}

对于多维结果,Array.newInstance的强制转换是必需的。 不再@SuppressWarnings("unchecked")

而不是传递collections[0].size(),它可能足以通过0