2

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

我正在使用一些 java 集合(准确地说是链表)动态构建表面,然后使用一些技巧将它们转换为 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...elements)。)
4

1 回答 1

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

于 2012-09-28T14:24:43.997 回答