[英]Java Reflection: How to obtain an instance of Class<T> from the ParameterizedType.getActualTypeArguments() array?
What I'm trying to do is to get a generic typearg of a Field using我想要做的是使用一个 Field 的通用 typearg
Type type = f.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) type;
// ...
Class<?> typearg0 = ??? // ptype.getActualTypeArguments()[0]
}
(where f
is an instance of java.lang.Field
). (其中
f
是java.lang.Field
的一个实例)。 I need that instance of Class<?>
to perform a Foo.class.isAssignableFrom(typearg0)
check later, which only takes Class<T>
es as an argument.我需要
Class<?>
的实例来执行Foo.class.isAssignableFrom(typearg0)
检查,它只需要Class<T>
es作为参数。 At the same time, I know (or expect) said typearg0
to be a parameterized type as well , so there's a contradiction: typearg0
cannot be Class<?>
and ParameterizedType
at the same time, because Class<?>
is itself a class and does not implement ParameterizedType
.同时,我知道(或期望)说
typearg0
也是参数化类型,因此存在矛盾: typearg0
不能同时是Class<?>
和ParameterizedType
,因为Class<?>
本身就是 class 和不实现ParameterizedType
。
Can I achieve the isAssignableFrom()
check in any other way?我可以以任何其他方式实现
isAssignableFrom()
检查吗? Or is my goal generally impossible to achieve?或者我的目标通常是不可能实现的?
Thank you very much!非常感谢!
Edit:编辑:
Here is an example:这是一个例子:
Suppose you expect a Field of type Map<Foo, Set<Bar>>
, but all you got is a java.lang.reflect.Field
instance.假设您期望
Map<Foo, Set<Bar>>
类型的 Field,但您得到的只是java.lang.reflect.Field
实例。 Now, you don't want it to precisely match Map<Foo, Set<Bar>>
, you just want the respective types to be instances of Map
or Set
.现在,您不希望它精确匹配
Map<Foo, Set<Bar>>
,您只希望各自的类型是Map
或Set
的实例。 It is not a rigid specification check, it's more of a "sanity check".这不是严格的规范检查,更像是“健全性检查”。 I would attempt this check like this:
我会尝试这样的检查:
.getType()
).getType()
)Map
is assignable from the field typeMap
是否可从字段类型分配.getGenericType()
).getGenericType()
)Foo
(this should be an exact match)Foo
(这应该是完全匹配的)Set
is assignable from this nested typeSet
是否可以从此嵌套类型分配ParameterizedType
and cast itParameterizedType
并强制转换Bar
(this should be an exact match)Bar
(这应该是完全匹配的) However, I don't know how to achieve 5 and/or 6.但是,我不知道如何达到 5 和/或 6。
(using java 11) (使用 java 11)
Just like you've done with Map
, Set
is likely to be an instance of ParameterizedType
so you can check it and then cast it.就像您对
Map
所做的一样, Set
很可能是ParameterizedType
的一个实例,因此您可以检查它然后进行转换。
From that ParameterizedType
(which represents the Set<Something>
), you can get use getRawType
to get a Set
.从那个
ParameterizedType
(代表Set<Something>
),您可以使用getRawType
来获取Set
。 That's a Type
too -- but this should be safely castable to Class
.这也是一个
Type
——但这应该可以安全地转换为Class
。 Just in case it's not, you can use a fallback and load the class using its name.以防万一,您可以使用后备并使用其名称加载 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*/ }
Here's a full 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";
}
}
Output: Output:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.