1

TypeTools Resolving generic type information with TypeToolsを使用しようとして惨めに失敗した後、代わりにhttps://github.com/cowtowncoder/java-classmateを使用しようとしています。

誰かがこのコードを修正するのを手伝ってくれますか?

public T fromMap(S map) {
    TypeResolver typeResolver = new TypeResolver();        
    ResolvedType type = typeResolver.resolve((new MapperImpl<T, S>() {}).getClass());
    List<ResolvedType> params = type.typeParametersFor(MapperImpl.class);
    ResolvedType typeT = params.get(0);

    ObjectMapper objectMapper = new ObjectMapper();
    T obj = objectMapper.convertValue(map, (Class<T>) typeT.getErasedType());
    return obj;

}

このエラーが発生しています:

java.util.LinkedHashMap を LoginInputMapTest$Foo にキャストできません java.lang.ClassCastException at shouldMapToFoo(LoginInputMapTest.java:83)

この最小限のテスト ケースで:

public static class Foo {
       private String a;

        public String getA() {
            return a;
        }

        public void setA(String a) {
            this.a = a;
        }

   }

   @Test
   public void shouldMapToFoo() {
       Map<String, Object> map = new HashMap<>();
       map.put("a", "aaa");

       Mapper<Foo, Map<String, Object>> mapper = new MapperImpl<>();
       Foo foo = mapper.fromMap(map);
       Assert.assertEquals(foo.getA(), map.get("a"));
   }
4

2 に答える 2

3

fromMap型変数にバインドされた提供された型引数を取得するために、メソッド内でできることは何もありませんT

Mapper専用の実装を作成することをお勧めしますFoo

class FooMapperImpl<S> implements Mapper<Foo, S> {
    public Foo fromMap(S map) {
        ObjectMapper objectMapper = new ObjectMapper();
        Foo obj = objectMapper
                .convertValue(map, Foo.class);
        return obj;
    }
}

(ソースタイプSが常にMap.

于 2014-10-07T15:22:14.477 に答える
0

T型変数 ( 、 )に関して、Java ジェネリック型が機能する方法を完全には理解していないように思えますS。これについて詳しく知るには、次のサイトを参照してください。

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html

ただし、基本的に型変数は、実行時のジェネリック型情報を保持しません。Classしたがって、名目上、特定のパラメーター化を使用してメソッドを呼び出している間は、適切なパラメーター化された実際のインスタンスを渡さない限り、何も起こりません。したがって、バイトコードにコンパイルされたメソッドは次のようなものです。

public Object fromMap(Object map) { ... }

Mapここで、 asを渡すとmap、実行時の型は単純にMap.classなり、指定された型パラメーターはありません。Java 値には、実行時の型のパラメーター化情報がありません。基になるクラスは、たとえば、Map<String,Number>との間で同じMap<UUID,byte[]>です。パラメーターの宣言は Java コンパイラーにのみ影響し、値の型が適切にキャストされるようにするために必要なキャストが追加されます。

残念ながら、そこにある情報を見つけることができるライブラリはありません。したがって、あなたが提案する使用法をそのまま実装することはできません。

これは、入力を渡すことができなかったという意味ではなく、外部から渡す必要があることを意味します。基本的なジャクソンでは、次TypeReferenceを使用できます。

new TypeReference<Map<KeyType, ValueType>>() { };

type への参照を構築しますMap<KeyType,ValueType>TypeFactoryまたは、 ;を使用してプログラムでこれらを構築することもできます。何かのようなもの:

mapper.getTypeFactory().constructMapType(Map.class, KeyType.class, ValueType.class);
// or with recursively constructing nested generic types

現在:ClassMate逆に、クラス定義から型情報を抽出できます。フィールドを持つクラス、ジェネリック型宣言を使用するメソッドがある場合、宣言されたパラメーター化を簡単に見つけるのは困難です。しかし、これがあなたが実際に望んでいるもの、または必要としているものとは思えません。むしろ、Jackson の型処理機能を使用してビルドできるはずです。

于 2015-05-18T22:19:30.947 に答える