2012-03-29 3 views
1
public class A<T> { 
    public <K> void m(A<K> target) { 
     // determine if T equals K 
    } 
} 

<T><K>이 같은 유형인지 확인 할 수 있습니까?제네릭 유형이 같은지 확인

+0

IIRC에서는 유형 정보가 런타임시 지워집니다 (비표준 코드와의 하위 호환성). 그렇기 때문에 나는 대답이 '아니오'라고 확신한다. – jpm

+2

이것은 제네릭의 적절한 사용이 아닙니다. – ControlAltDel

+0

제네릭을 사용할 수있는 일반적인 경우 중 하나라고 확신합니다. –

답변

6

예, 이것은 일반 TypeReference와 동일한 방식으로 작동합니다. 일반적으로 유형이 삭제됩니다하지만 익명의 내부 클래스와 함께 작동 :

public abstract class A<T> { 

    private Type type; 

    public A() { 
     Type superclass = getClass().getGenericSuperclass(); 
     this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; 
    } 

    public <K> void m(A<K> target) { 
      System.out.println(type.equals(target.type)); 
    } 
} 

그것을 사용하려면 :

A<String> as = new A<String>(){}; 
    A<String> a2s = new A<String>(){}; 
    A<Integer> ai = new A<Integer>(){}; 

    as.m(a2s); // prints true 
    as.m(ai); // prints false 

클래스는 추상적 일 필요는 없습니다하지만 그것은 익명의 내부 클래스 있도록하는 알림 역할 . 유일한 단점은 {}을 마지막에 넣어야한다는 것입니다.

+0

추상 클래스를 사용한 악의적 인 해킹을위한 보너스 포인트 - OP이지만 일반적으로이를 수행 할 방법이 없으며 "익명 내부 클래스"해킹 없이는 할 수 없습니다. –

+0

Yepp, 그들은 익명의 내부 클래스가되어야하고, 내 대답이 업데이트되었습니다. – Andrejs

0

인스턴스가 T이거나 클래스가 A 또는이를 비교하려는 메소드로 전달 된 경우에만 해당됩니다. 유형 - 삭제는 ...

1

아니, 당신이 올 수있는 가장 가까운입니다

public class A<T> { 
    private Class<T> _type; 

    public A(Class<T> type) { 
    assert type != null; 
    _type = type; 
    } 

    public <K> void m(A<K> target) { 
    if (target != null && target._type == this._type) { 
     ... 
    } 
    } 

당신은 EnumMap 같은 종류의 생성자 매개 변수로 Class<T>을 전달하는 관용구를 볼 수 있습니다.

2

javas 유형 지우기 때문에 쉽지 않습니다. 런타임시 T 및 K에 대한 유형 정보가 손실됩니다.

그러나 당신은 당신이 컴파일시에 사람들을 확인할 수 있습니다 해당 유형의 인스턴스를 얻을 수있는 경우 : 당신이 개체의 인스턴스에 액세스해야하는 것을 의미하지만

public class A<T> { 

    private T t; 

    public T getT() { return t; } 

    public A(T t) { 
     this.t = t; 
    } 

    public <K> m(A<K> target) { 
     // determine if T equals K 
     boolean areEqual = t.getClass().equals(target.getT().getClass()); 
    } 
} 

합니다.

+0

문제는'getT()'가 null을 반환 할 수 있습니다. –

+0

사실입니다. 이전에이를 확인하고 areEqual을 false로 설정할 수 있습니다. – david

0

클래스의 제네릭 형식을 알려주는 코드입니다. target.getClass()에 대한의 일반적인 유형을 비교하려면이 옵션을 사용

/** 
* Gets a list of type Class that contains the type arguments that a child class has used to extend a generic base 
* class. 
* 
* For example, if a class called ChildClass has this signature: 
* 
* <code> 
* public class ChildClass extends ParentClass<Integer, String> 
* </code> 
* 
* then the list returned would have two entries: Integer and String. 
* 
* @param baseClass The generic base class being extended. 
* @param childClass The child class that is doing the extending. 
* @return A list of type Class containing the raw classes for the type arguments. 
*/ 
public <T> List<Class<?>> getTypeArguments(Class<T> baseClass, Class<? extends T> childClass) { 

    Map<Type, Type> resolvedTypes = new HashMap<Type, Type>(); 
    Type type = childClass; 

    // start walking up the inheritance hierarchy until we hit baseClass 
    while (getClass(type) != null && !getClass(type).equals(baseClass)) { 
     if (type instanceof Class) { 
      // there is no useful information for us in raw types, so just keep going. 
      type = ((Class<?>) type).getGenericSuperclass(); 
     } else { 
      ParameterizedType parameterizedType = (ParameterizedType) type; 
      Class<?> rawType = (Class<?>) parameterizedType.getRawType(); 

      Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); 
      TypeVariable<?>[] typeParameters = rawType.getTypeParameters(); 
      for (int i = 0; i < actualTypeArguments.length; i++) { 
       resolvedTypes.put(typeParameters[i], actualTypeArguments[i]); 
      } 

      if (!rawType.equals(baseClass)) { 
       type = rawType.getGenericSuperclass(); 
      } 
     } 
    } 

    // finally, for each actual type argument provided to baseClass, determine (if possible) the raw class for that 
    // type argument 
    Type[] actualTypeArguments; 
    if (type instanceof Class) { 
     actualTypeArguments = ((Class<?>) type).getTypeParameters(); 
    } else { 
     actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); 
    } 

    // convert types to their raw classes 
    List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>(); 
    for (Type baseType : actualTypeArguments) { 
     while (resolvedTypes.containsKey(baseType)) { 
      baseType = resolvedTypes.get(baseType); 
     } 
     typeArgumentsAsClasses.add(getClass(baseType)); 
    } 

    return typeArgumentsAsClasses; 

} 

/** 
* Gets the Class for a Type. If the Type is a variable type, null is returned. 
* 
* @param type The Type to get the Class for 
* @return Returns the Class, unless Type is a variable type, then null is returned. 
*/ 
public Class<?> getClass(Type type) { 

    Class<?> returnClass = null; 

    if (type instanceof Class) { 
     returnClass = (Class<?>) type; 
    } else if (type instanceof ParameterizedType) { 
     returnClass = getClass(((ParameterizedType) type).getRawType()); 
    } else if (type instanceof GenericArrayType) { 
     Class<?> componentClass = getClass(((GenericArrayType) type).getGenericComponentType()); 
     if (componentClass != null) { 
      returnClass = Array.newInstance(componentClass, 0).getClass(); 
     } 
    } 

    return returnClass; 

} 
관련 문제