使用java classmate解析泛型类型

使用java classmate解析泛型类型,java,generics,classmate,Java,Generics,Classmate,在尝试使用TypeTools失败之后,我正尝试使用它 有人能帮我修复这个代码吗 public T fromMap(S map) { TypeResolver typeResolver = new TypeResolver(); ResolvedType type = typeResolver.resolve((new MapperImpl<T, S>() {}).getClass()); List<ResolvedType> par

在尝试使用TypeTools失败之后,我正尝试使用它

有人能帮我修复这个代码吗

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;

}
public T fromMap(S map){
TypeResolver TypeResolver=新的TypeResolver();
ResolvedType type=typeResolver.resolve((新的MapperImpl(){}).getClass());
List params=type.typeparameters(MapperImpl.class);
ResolvedType typeT=params.get(0);
ObjectMapper ObjectMapper=新的ObjectMapper();
T obj=objectMapper.convertValue(map,(Class)typeT.get橡皮擦类型());
返回obj;
}
我得到这个错误:

无法将java.util.LinkedHashMap强制转换为LoginInputMapTest$Foo java.lang.ClassCastException位于 shouldmaptoo(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"));
   }
公共静态类Foo{
私人字符串a;
公共字符串getA(){
返回a;
}
公共空集a(字符串a){
这个a=a;
}
}
@试验
public void shouldMapToFoo(){
Map Map=newhashmap();
地图放置(“a”、“aaa”);
Mapper Mapper=新的MapperImpl();
Foo-Foo=mapper.fromMap(map);
Assert.assertEquals(foo.getA(),map.get(“a”);
}

fromMap
方法中,无法获取绑定到类型变量
T
的类型参数

我建议您专门为
Foo
创建一个
Mapper
实现

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;
    }
}
类FooMapperImpl实现映射器{
公共Foo fromMap(S地图){
ObjectMapper ObjectMapper=新的ObjectMapper();
Foo obj=对象映射器
.convertValue(映射,Foo.class);
返回obj;
}
}

(虽然我不明白为什么您需要源类型
S
,如果它始终是
Map

在我看来,您似乎不完全了解Java泛型类型在类型变量方面的工作方式(
t
S
)。了解更多信息的好地方是:

但基本上类型变量不携带任何运行时泛型类型信息。因此,当您名义上调用具有特定参数化的方法时,除非您传递实际的
Class
合适的参数化实例,否则不会发生任何事情。因此,编译成字节码的方法只不过是:

public Object fromMap(Object map) { ... }
现在,如果将
Map
作为
Map
传递,则运行时类型将只是
Map.class
,并且没有指定类型参数:Java值没有任何运行时类型参数化信息。底层类在
Map
Map
之间是相同的。参数声明只影响Java编译器,它添加了必要的强制转换,以确保值类型得到正确的强制转换

不幸的是,没有一个图书馆能找到那里的信息。因此,您建议的用法不可能按原样实现

这并不意味着你不能通过打字,但它意味着它必须从外部通过。使用basic Jackson,您可以使用
TypeReference

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

现在:
ClassMate
可以从类定义中提取类型信息。如果您有一个带有字段的类,即使用泛型类型声明的方法,则很难找到声明的参数化。但听起来这并不是你真正想要或需要的。相反,您应该能够使用Jackson的类型处理功能构建它。

您的MapperImpl有什么作用吗?看起来您创建了一个匿名类而没有实际访问它。或者这只是一个缩写?匿名类是用来提供子类型的。我认为您需要它来解析泛型类型。看这个例子:你是对的,没有必要用S参数化映射器接口。为什么你说我无法得到类型T。这不是像TypeTools和classmate这样的库的目的吗?我试图做的正是他们在“4.真实世界用法”@dmz73中描述的,这看起来完全不同。他们可以从
处理程序
中提取类型。但是您的
fromMap
方法没有任何内容可用于提取为
T
提供的类型参数。
mapper.getTypeFactory().constructMapType(Map.class, KeyType.class, ValueType.class);
// or with recursively constructing nested generic types