2014-11-08 2 views
0

유형 변수가 메소드의 매개 변수로 사용되는 일반 클래스가 있습니다. 바운드 된 와일드 카드를 사용하여 Set, Map 또는 List에서 제네릭 클래스의 인스턴스를 검색 할 때이 메서드를 호출하려면 어떻게해야합니까?제네릭 클래스에서 와일드 카드 메서드를 호출하는 방법은 무엇입니까?

일반 클래스의 슈퍼 :

//Verifier.java 
import java.lang.annotation.Annotation; 

public interface Verifier<A extends Annotation> { 
    // A verifier needs the annotation to extract verification information. 
    public boolean verifyValue(Object value, A annotation); 
} 

고정 구현 :

//MinMaxVerifyer.java 
public class MinMaxVerifyer implements Verifier<MinMax> { 
    @Override 
    public boolean verifyValue(Object value, MinMax annotation) { 
     if (!(value instanceof Number)) return false; 

     long l = ((Number)value).longValue(); 
     long min = annotation.min(); 
     long max = annotation.max(); 

     return l >= min && l <= max; 
    } 
} 

예에서 사용 된 주석 :

//MinMax.java 
import java.lang.annotation.*; 

@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Target(ElementType.METHOD) 
@Inherited 
public @interface MinMax { 
    long min() default Long.MIN_VALUE; 
    long max() default Long.MAX_VALUE; 
} 

잘못된 호출을 포함하는 클래스 :

import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 
import java.util.*; 

public class ParameterVerifier { 
    private static final Map<String, Verifier<? extends Annotation>> verifyers 
     = new HashMap<>(); 

    static { 
     verifyers.put("MinMax", new MinMaxVerifyer()); 
     // verifyers.put(Range.class, new RangeVerifier()); 
     // verifyers.put(NotNull.class, new NotNullVerifier()); 
    } 

    public void validate(Method method, Object value) { 
     for (Annotation annotation : method.getAnnotations()) { 
      String name = annotation.getClass().getSimpleName(); 
      Verifier<? extends Annotation> verifier = verifyers.get(name); 

      if (verifier != null) { 
       boolean valid = verifier.verifyValue(value, annotation); 
       //^The method 
       // verifyValue(Object, capture#5-of ? extends Annotation) 
       // in the type Verifier<capture#5-of ? extends Annotation> 
       // is not applicable for the arguments (Object, Annotation) 
      } 
     } 
    } 
} 

사용자가 자신의 Annotation/Verifier 쌍을 추가 할 수 있도록이 작업을 시도하고 Verifier를 Annotation 하위 클래스로 매개 변수화해야합니다. ParameterVerifier (공개 API 인 확인 프로그램이 아님)에서 약간 캐스트해야한다면 상관하지 않습니다. 필자는 명확한 의미를 위해 여기에 생략 된 몇 가지 추가 논리를 사용하여 쌍 유형 안전을 추가하는 방법을 알고 있습니다.

관련 : The method validate(capture#2-of ? extends Object) in the type Validator<capture#2-of ? extends Object> is not applicable for the arguments (String)Java generic/wildcard type mismatch 모두 특정 Verifier 하위 유형으로 제한하거나 Verifier에서 유형 변수를 제거 할 것을 제안합니다. 나는 더 우아한 해결책을 찾고 있습니다. (MinMaxVerifyer.java를 변경 불가능하다고 생각하고 다른 것들에 대해서만 작업하십시오.)

+0

나는 그것이 Methos는에 일반 매개 변수를 이동하지 않고 가능하다 모르겠습니다. 예를 들면 :'minmaxVerifier.varifyValue (null, somethingNotMinMax); '이것은보기 흉하게 보인다. –

+0

"좀 더 명확한 논리를 위해 여기에 생략 된 여분의 논리를 사용하여 쌍 유형 안전을 추가하는 방법을 알고 있습니다." –

+0

나는 그 논평을 보았다. 나는 그것이 가능하다는 것을 의심한다. 유효한 Java 구문이 아닌'interface Verifier '과 같은 것이 필요합니다. –

답변

0

나는 이것을 이전에 발견하지 못했습니다. 난 제네릭의 모든 조합을 시도 할 줄 알았는데. 이것은 컴파일하고 작업을 완벽하게 수행합니다.

  • 검색된 요소에서 와일드 카드를 제거한 후 컴파일러에게 전송하면 안전합니다.
import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 
import java.util.*; 

public class ParameterVerifier { 

    private static final Map<String, Verifier<? extends Annotation>> verifiers 
     = new HashMap<>(); 

    static { 
     verifiers.put(Range.class.getSimpleName(), new RangeVerifyer()); 
    } 

    public void validate(Method method, Object value) { 
     for (Annotation annotation : method.getAnnotations()) { 
      String name = annotation.getClass().getSimpleName(); 
      @SuppressWarnings("unchecked") 
      Verifier<Annotation> verifier = 
       (Verifier<Annotation>)verifiers.get(name); 
      if (verifier != null) { 
       boolean valid = verifier.verify(value, annotation); 
      } 
     } 
    } 
} 
+0

경고를 억제하는 것은 일반적으로 좋은 생각이 아닙니다. 경고는 목적이 있습니다. 코드가 잘못되어 문제가 발생할 수 있음을 경고합니다. 코드가 실행될 수도 있지만 예측할 수없는 오류가 발생할 가능성이 있습니다. – MSB

+0

"코드가 잘못되어 문제가 발생할 수 있음을 경고합니다."사실이 아닙니다.컴파일러는 사용자가 원하는 모든 것을 고려할 수 없기 때문에 코드가 안전하다는 것을 확인할 수 없습니다. 이 경우 사용자가 코드가 안전하다는 것을 증명할 수 있으면'@ SuppressWarnings '이 적절한 조치 과정입니다. (Effective Java, 항목 24) (Google "효과적인 java pdf") –

관련 문제