2013-06-25 2 views
1

내 프로그램은이 유형의 매개 변수를 허용하는 작업에 매핑 된 매개 변수 유형을 저장합니다. 명시 적 형식을 사용하여 저장된 연산을 검색 할 때 주어진 유형의 객체를 매개 변수로 사용하여 연산의 메서드를 호출해도 문제가 없습니다. 그러나, 작업의 방법은 오류가 결과를 호출 만 암시 적으로 알려져있는 유형을 사용하는 경우 :보기 자바의 관점에서 물론런타임 유형 정보로 일반 메소드를 호출하는 방법은 무엇입니까?

public class StoredArgumentTypeProblem { 
    static class Operation<T> { 
     T apply(T arg) { 
      return arg; 
     } 
    } 

    static class OperationContainer { 
     private Map<Class<?>, Operation<?>> storedOperations = new HashMap<>(); 
     public <T> void put(Class<T> argType, Operation<T> opp) { 
      storedOperations.put(argType, opp); 
     } 

     public Class<?> getSomeStoredKey() { 
      return storedOperations.keySet().iterator().next(); 
     } 

     public <T> Operation<T> get(Class<T> type) { 
      // unchecked cast, but should work given restrictions on put. 
      return (Operation<T>)storedOperations.get(type);  
     } 
    } 

    public void test() { 
     OperationContainer container = new OperationContainer(); 
     container.put(Integer.class, new Operation<Integer>()); 
     container.get(Integer.class).apply(new Integer(1234)); 

     Class<?> keyType = container.getSomeStoredKey(); 

     // ERROR: method apply in Operation<T> cannot be applied to given types 
     container.get(keyType).apply(keyType.cast(new Integer(5678))); 
    } 
} 

오류가 완전히 정당화를; # 1의 '?'캡처 '?'캡처 # 2와는 아무런 관련이 없습니다. 그러나 우리 인간은이 경우 keyType에 의해 캐스팅 된 인자와 함께 'apply (...)'를 호출하면 작동한다는 것을 알 수 있습니다.

은 동적으로 저장 작업을 적용 어떻게 든 '바보'자바 가능하고 있습니까?
몇 가지 유형의 캐스팅을 사용하고 있습니까? 주석 사용? 다른 아이디어? ...

답변

2

이 문제는 와일드 카드 캡쳐의 한계와 관련이 있습니다. 와일드 카드는 본질적으로 독립형 매개 변수처럼 작동하며 매개 변수 간의 관계를 표현할 방법이 없습니다. 이 문제를 해결하기 위해 실제 형식 매개 변수를 사용하여 관계를 표현하는 "도우미 캡처"메서드를 사용할 수 있습니다.

private <T> void apply(
     OperationContainer container, 
     Class<T> keyType, 
     Object argument 
) { 
    T castArgument = keyType.cast(argument); 
    Operation<T> operation = container.get(keyType); 
    operation.apply(castArgument); 
} 

public void test() { 
    OperationContainer container = new OperationContainer(); 
    container.put(Integer.class, new Operation<Integer>()); 
    container.get(Integer.class).apply(new Integer(1234)); 

    Class<?> keyType = container.getSomeStoredKey(); 

    apply(container, keyType, new Integer(5678)); 
} 
0

위의 질문을 작성할 때 다음 해결책이 나에게 발생했습니다. 제네릭 및 반사로 인한 문제를 해결하기

...
더 반사를 사용!

을 감안할 때 OperationOperationContainer

사용 Class.getMethod(…)Method.invoke(…) 위의 정의 :

public void test() { 
     OperationContainer container = new OperationContainer(); 
     container.put(Integer.class, new Operation<Integer>()); 
     container.get(Integer.class).apply(new Integer(1234)); 
     Class<?> keyType = container.getSomeStoredKey(); 

     // ERROR: method apply in Operation<T> cannot be applied to given types 
     // container.get(keyType).apply(keyType.cast(new Integer(5678))); 

     Operation<?> storedOpp = container.get(keyType); 
     try { 
      storedOpp.getClass().getMethod("apply", keyType).invoke(storedOpp, keyType.cast(new Integer(5678))); 
     } catch (IllegalAccessException | IllegalArgumentException | 
       InvocationTargetException | NoSuchMethodException ex) { 
      throw new Error(ex); 
     } 
    } 
+0

주석 및 더 나은 솔루션을 환영합니다. –

관련 문제