2014-10-07 2 views
1

TypeTools Resolving generic type information with TypeTools을 비참하게 사용하지 않으려 고 시도한 후 https://github.com/cowtowncoder/java-classmate을 대신 사용하려고합니다.자바 클래스 메이트로 제네릭 타입을 해결

누군가이 코드를 수정하도록 도움을 줄 수 있습니까? 이 최소한의 테스트 케이스와

java.util.LinkedHashMap cannot be cast to LoginInputMapTest$Foo java.lang.ClassCastException at shouldMapToFoo(LoginInputMapTest.java:83)

:

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 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")); 
    } 
+0

MapperImpl이 어떤 작업을 수행합니까? 실제로 액세스하지 않고 익명의 클래스를 만든 것처럼 보입니다. 아니면 그냥 약어인가요? –

+0

익명 클래스는 하위 유형을 제공합니다. 제네릭 형식을 해결하는 데 필요하다고 생각합니다. 이 예제를 참조하십시오 : https://github.com/cowtowncoder/java-classmate#resolving-type-parameters-for-a-class – dmz73

답변

2

이었다 제공하는 형식 인수를 얻기 위해 당신이 당신의 fromMap 메서드 내에서 할 수있는 일은 없다 귀하의 유형 변수 T에 바인딩됩니다.

Foo에 대해 특별히 Mapper 구현을 만드는 것이 좋습니다. (이 항상 Map 될 것 경우는 소스 유형 S 필요 왜 표시되지 않습니다 있지만.)

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; 
    } 
} 

+0

당신은 S와 Mapper 인터페이스를 매개 변수화 할 필요가 없습니다. 왜 그렇습니까? T 타입을 얻기 위해 할 수있는 일은 아무것도 없습니다 .TypeTools와 클래스 메이트 같은 라이브러리의 목적이 아닌가요? – dmz73

+0

내가하려고하는 것은 정확하게 "4. 실제 사용"에서 설명하는 것입니다. http://www.cowtowncoder.com/blog/archives/2012/04/entry_471.html – dmz73

+0

@ dmz73 그것은 완전히 다른 것처럼 보입니다. 그들은'handler'에서 타입을 추출 할 수 있습니다. 하지만 당신의'fromMap' 메소드는'T'에 제공된 타입 인자를 추출하는데 사용할 수있는 것이 아무것도 없습니다. –

0

당신이 완전히 길 자바 제네릭 형식을 이해하지 못하는 나에게 보인다 형식 변수 (T, S)와 관련하여 작업하십시오. 이에 대한 자세한 내용을 배울 수있는 좋은 장소입니다 :

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

하지만 기본적으로 변수는 어떤 런타임 제네릭 형식 정보를 전달하지 않는 입력합니다. 따라서 특정 매개 변수화 방법으로 명목상 메서드를 호출하는 동안 실제 Class 인스턴스를 매개 변수화 된 값으로 전달하지 않으면 아무 일도 발생하지 않습니다. 당신이 Mapmap으로, 실행시의 형태는 단순히 Map.class 될 것 통과하고 지정된 어떤 형태 파라미터가없는 경우,

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

지금 : 그래서 바이트 코드로 컴파일 당신의 방법보다 좀 더 자바 값은 어떤 실행시의 형태가없는 매개 변수화 정보. 기본 클래스는 예를 들어 Map<String,Number>Map<UUID,byte[]> 사이에서 동일합니다. 매개 변수의 선언은 Java 컴파일러에만 영향을 미칩니다. Java 컴파일러는 값 유형이 올바르게 형변환되도록 필요한 형변환을 추가합니다.

라이브러리에 정보가 있으면 찾을 수 없습니다. 그래서 당신이 제안한대로 사용은 현재대로 구현할 수 없습니다.

이것은 입력을 전달할 수 없다는 의미가 아니며 외부에서 전달되어야 함을 의미합니다.

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

Map<KeyType,ValueType>를 입력 참조를 만들 것입니다 : 기본 잭슨, 당신은 당신이 사용할 수있는 TypeReference 있습니다. 또는 TypeFactory을 사용하여 프로그래밍 방식으로 생성 할 수 있습니다. 이제

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

: 같은 ClassMate 수, 클래스 정의의 밖으로 반대로, 추출 유형 정보. 필드가있는 클래스, 제네릭 형식 선언을 사용하는 메서드가 있으면 선언 된 매개 변수를 쉽게 찾을 수 없습니다. 그러나 실제로는 여기에 원하는 것이 있거나 필요로하는 것처럼 들리지는 않습니다.대신 Jackson의 유형 처리 기능을 사용하여 빌드 할 수 있어야합니다.