public class A<T> {
public <K> void m(A<K> target) {
// determine if T equals K
}
}
是否可以檢查<T>
和<K>
是否是相同的類型?確定泛型類型是否相同
public class A<T> {
public <K> void m(A<K> target) {
// determine if T equals K
}
}
是否可以檢查<T>
和<K>
是否是相同的類型?確定泛型類型是否相同
是,這種工作方式的一般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
類並不一定是抽象的,但它作爲一個提醒,使其匿名內部類。唯一真正的缺點是你必須把{}
結束。
你的邪惡攻擊與抽象類的加分 - 但OP,通常沒有任何方法可以做到這一點,沒有「匿名內部類」攻擊,絕對沒有辦法做到這一點。 – 2012-03-29 19:30:49
葉普,他們必須是匿名的內部類,更新我的答案 – Andrejs 2012-03-29 19:51:09
不是真的,只有當你有一個T
的實例或者類傳入A
或想要比較它們的方法。類型擦除...
沒有,你能來最接近的是:
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) {
...
}
}
你可以看到在類型傳遞Class<T>
作爲構造函數的參數一樣EnumMap
的成語。
這並不容易,因爲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());
}
}
但是這意味着你需要訪問對象的實例。
問題是'getT()'可以返回'null' – 2012-03-29 19:04:08
這是真的。你可以在之前檢查並設置areEqual爲false。 – david 2012-03-29 19:05:39
這是我寫的代碼,它會告訴你一個類的泛型類型。使用此來比較泛型類型A對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;
}
IIRC,類型信息在運行時被擦除(爲了向後兼容非泛型代碼)。因此,我很肯定答案是否定的。 – jpm 2012-03-29 18:55:48
這不是一個適當的泛型使用 – ControlAltDel 2012-03-29 18:56:31
我敢肯定,這是使用泛型的可能和正常情況之一。 – 2012-03-29 18:59:53