2

だから、私が取り組んでいるプラットフォーマーの物理システムに 2D 配列を使用しています。残念ながら、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);

その後、すべてがクラッシュし、Object 型を PhysSurface 型に変換できないことを示す ClassCastException が発生します。スタック トレースは次のとおりです。

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 に答える