就像你对Map 所做的那样,Set 很可能是ParameterizedType 的一个实例,所以你可以检查它然后再转换它。
从ParameterizedType(代表Set<Something>),您可以使用getRawType 获得Set。那也是Type——但这应该可以安全地转换为Class。万一不是,您可以使用后备并使用其名称加载类。
final Type valueType = mapType.getActualTypeArguments()[1];
final ParameterizedType pValueType = (ParameterizedType) valueType;
final Class<?> valueClass = pValueType.getRawType() instanceof Class ?
((Class<?>) pValueType.getRawType()) :
// Should be castable, but just in case it's not, fallback
getClass().getClassLoader().loadClass(
pValueType.getRawType().getTypeName()
);
if (Set.class.isAssignableFrom(valueClass)) { /* do something*/ }
这是完整的runnable example。
class Foo {}
class Bar {}
interface MyValidMap extends Map<Foo, Set<Bar>> {}
public class Application {
public final HashMap<Foo, HashSet<Bar>> good = null;
public final Map<Foo, Set<Bar>> better = null;
public final String notAMap = null;
public final Map<String, Set<Bar>> badKey = null;
public final Map<Foo, List<String>> badValue = null;
public final Map<Foo, Set<String>> badSetElems = null;
public final MyValidMap noTypeParamMap = null;
public static void main(String[] args) throws Exception {
for (Field field : Application.class.getFields()) {
System.out.println(field.getName() + " - " + fieldMatches(field));
}
}
private static String fieldMatches(Field mapField) throws Exception {
if (!Map.class.isAssignableFrom(mapField.getType())) {
return "Field is not a Map";
}
if (!(mapField.getGenericType() instanceof ParameterizedType)) {
// We know it's a map, but it doesn't have type params. Probably something
// like this: class MyStringMap implements Map<String, String>. You can do
// something with getGenericInterfaces() but this seems so unlikely that
// it could just be ignored.
return "TODO";
}
final ParameterizedType mapType = (ParameterizedType) mapField.getGenericType();
final Type keyType = mapType.getActualTypeArguments()[0];
final Type valueType = mapType.getActualTypeArguments()[1];
if (Foo.class != keyType) {
return "Map's key type is not Foo";
}
if (!(valueType instanceof ParameterizedType)) {
// Same problem as above. May be a Set without type params
return "Map's value is (probably) not a Set";
}
final ParameterizedType pValueType = (ParameterizedType) valueType;
final Class<?> valueClass = pValueType.getRawType() instanceof Class ?
((Class<?>) pValueType.getRawType()) :
Application.class.getClassLoader().loadClass(
pValueType.getRawType().getTypeName()
);
if (!Set.class.isAssignableFrom(valueClass)) {
return "Map's value is not a Set";
}
final Type setElemType = pValueType.getActualTypeArguments()[0];
if (setElemType != Bar.class) {
return "Set's elements are not Bars";
}
return "Looks good";
}
}
输出:
good - Looks good
better - Looks good
notAMap - Field is not a Map
badKey - Map's key type is not Foo
badValue - Map's value is (probably) not a Set
badSetElems - Set's elements are not Bars
noTypeParamMap - TODO