0

私のアプリケーションは投げています

java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

このコードの場合:

public class DsMap<K,V> implements Map<K, V>{
    protected Class<K> kClazz;
    protected Class<V> vClazz;  

    // Called during DS.getMap(mapName) method
    public DsMap(String name) {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        Type typeK = genericSuperclass.getActualTypeArguments()[0];
        Type typeV = genericSuperclass.getActualTypeArguments()[1];

        if (typeK instanceof Class) {
            this.kClazz = (Class<K>) typeK;
        } else if (typeK instanceof ParameterizedType) {
            this.kClazz = (Class<K>) ((ParameterizedType)typeK).getRawType();
        }

        if (typeV instanceof Class) {
            this.vClazz = (Class<V>) typeV;
        } else if (typeV instanceof ParameterizedType) {
            this.vClazz = (Class<V>) ((ParameterizedType)typeV).getRawType();
        }           
    }
}

私が達成しようとしているのは、実行時にクラス名Kを取得することです:V

これを行うなど:

Map<String,String> dsMap = DS.getMap(mapName);

andjava.lang.Stringのクラス名を取得するか、パラメーター化されたクラス名を取得します ( and をインスタンス化せずに)kClazzvClazzClass<K>Class<V>

私のコードで何が間違っている可能性がありますか?

4

3 に答える 3

1

パラメーター化された型は、ジェネリック型の具体的な実現を表します。ジェネリック型とパラメーター化された型の関係は、テンプレートドキュメントの関係と同じように考えることができます。テンプレートは、情報を入力する場所を示し、ドキュメントには実際に情報が入力されています。あなたの例では:

public class DsMap<K,V> implements Map<K, V>

DsMapとはどちらMapもジェネリック型 (またはテンプレート) です。それらの実際の汎用パラメーターは、クラス自体によって指定されていないため、コンパイラーによってキャプチャされません。つまり、それらの一般的な情報は実行時に利用できません。

実行時に実際のジェネリック パラメーターを取得するには、それらのパラメーターがクラス シグネチャの一部である必要があります。たとえば、クラスのこの単純な拡張は機能します。

public class DsMapIntegerString extends DsMap<Integer, String>

具体的なパラメーターを指定したため、によって返される型getClass().getGenericSuperclass()は実際にはパラメーター化されたクラスになり、コードは失敗しなくなります。

于 2013-04-02T18:13:36.120 に答える
0

目視検査によると、次のように変更してみてください。

static public class DsMap<K, V> implements Map<K, V> {

static public class DsMap<K, V> extends HashMap<K, V> {
于 2013-04-02T18:17:30.893 に答える
0

DsMapジェネリック インターフェイス ( Map<K,V>) を実装しますが、ジェネリック クラスを拡張しません。そのため、 にキャストできないgetClass().getGenericSuperclass()への参照を返します。java.lang.ObjectParameterizedType

この(ParameterizedType) getClass().getGenericSuperclass()トリックは、1) サブクラスがジェネリック クラスを拡張する場合、2) サブクラスがコンパイル時に型引数を宣言する場合にのみ適用されます。

例えば:

public abstract class DsMap<K, V> implements Map<K, V> {

...

public class StringIntDsMap extends DsMap<String, Integer> {

...

次に、getGenericSuperclass()を返しDsMapます。これは にキャストでき、から返された配列ParameterizedType内のエントリはにキャストできます。Type[]getActualTypeArguments()Class

残念ながら、これはあまり一般的な状態ではありません。単体テスト間でコードを共有するために頻繁に使用しました (コンパイル時にジェネリック型を宣言できます)。ただし、型が実行時まで使用できない場合には一般化されません。

于 2013-04-02T18:10:48.217 に答える