[英]Examine generic type of a method parameter
我不知道这是否可以用Java完成。 我找不到解决方案。
我想检查一个类中的所有方法,并找出带有通用信息的方法的参数。 例如,如果您有一个接口和一个类似于以下内容的实现者:
// Services are the objects i will examine
public interface Service<T extends DetailsModel> {
public Response findObject(RequestEvent<T> event);
}
public interface SomeObjectService extends Service<SomeObject> {
Response findObject(RequestEvent<SomeObject> event);
}
public class SomeObjectServiceImpl extends SomeObjectService {
public Response findObject(RequestEvent<SomeObject> event) {...}
}
// Events are the parameters of the services
public interface Event<T extends DetailsModel> {
Callback getCallback()
}
public abstract class AbstractEvent<T> implements Event<T> {
public Callback getCallback() {
return null;
}
}
public class RequestEvent<T> extends AbstractEvent<T> {
Handle<T> t;
public Handle<T> getHandle() {...}
}
在查看SomeObjectServiceImpl时,我尝试了各种方法来从RequestEvent中获取实际的T。 例如
public <D extends DetailsModel> void configure(Service<D> service) {
Method[] allDeclaredMethods = service.getClass().getDeclaredMethods();
for (Method declaredMethod : allDeclaredMethods) {
try {
Type[] parameterTypes = declaredMethod.getGenericParameterTypes();
if (parameterTypes.length == 1) {
Type parameterType = parameterTypes[0];
if (Event.class.isAssignableFrom((Class<?>) parameterType)) {
ParameterizedType type = ((ParameterizedType) ((Class) parameterType).getGenericSuperclass());
Type genericType = type.getActualTypeArguments()[0];
if (genericType != null && genericType instanceof Class) {
EventDescriber eventDescriber = new EventDescriber(
(Class<? extends Event>) parameterType,
(Class) genericType);
}
}
}
} catch (Exception e) {
logger.warn("Could not map " + declaredMethod, e);
}
}
然后,我希望对SomeObjectServiceImpl中的方法进行检查的结果是:
ServiceImpl:
findObject:
RequestEvent
SomeObject (I cant find this. Instead I find a TypeVariableImpl.)
您可以使用Java反射来做到这一点吗?
当然可以。 使用该Method
检索[通用参数类型] [1]。
Method method = ServiceImpl.class.getMethod("doSomething",
DoSomethingEvent.class);
ParameterizedType type = (ParameterizedType)method.getGenericParameterTypes()[0];
然后访问[原始类型] [2]和[实际类型参数] [3]。
type.getRawType();
type.getActualTypeArguments()[0]; // first type argument
这是一个有效的例子
public class Test {
public static void main(String[] args) throws Exception {
configure(new ServiceImpl());
}
public static <T> void configure(Service<T> service) {
Method[] allDeclaredMethods = service.getClass().getDeclaredMethods();
for (Method declaredMethod : allDeclaredMethods) {
try {
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
if (parameterTypes.length == 1) {
Class<?> parameterType = parameterTypes[0];
if (Event.class.isAssignableFrom(parameterType)) {
ParameterizedType type = ((ParameterizedType) declaredMethod
.getGenericParameterTypes()[0]);
Type typeArgument = type.getActualTypeArguments()[0];
System.out.println("Parameter type: " + type.getRawType() + ", Generic type argument: " + typeArgument);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
interface Response {
}
interface Service<T> {
public Response findObject(RequestEvent<T> event);
}
class ServiceImpl implements Service<SomeObject> {
public Response findObject(RequestEvent<SomeObject> event) {
return null;
}
public Response doSomething(DoSomethingEvent<SomethingAction> event) {
return null;
}
}
interface Event<T> {
}
interface SomethingAction {
}
class SomeObject {
}
class DoSomethingEvent<T> extends RequestEvent<T> {
}
interface Handle<T> {
}
class RequestEvent<T> implements Event<T> {
Handle<T> t;
public Handle<T> getHandle() {
return null;
}
}
它打印
Parameter type: class com.example.RequestEvent, Generic type argument: class com.example.SomeObject
Parameter type: class com.example.DoSomethingEvent, Generic type argument: interface com.example.SomethingAction
我只是做了同样的事情。 仅限于Iterable
,但反射代码将非常相似:
/**
* Assuming the given method returns or takes an Iterable<T>, this determines the type T.
* T may or may not extend WindupVertexFrame.
*/
private static Class typeOfIterable(Method method, boolean setter)
{
Type type;
if (setter) {
Type[] types = method.getGenericParameterTypes();
// The first parameter to the method expected to be Iterable<...> .
if (types.length == 0)
throw new IllegalArgumentException("Given method has 0 params: " + method);
type = types[0];
}
else {
type = method.getGenericReturnType();
}
// Now get the parametrized type of the generic.
if (!(type instanceof ParameterizedType))
throw new IllegalArgumentException("Given method's 1st param type is not parametrized generic: " + method);
ParameterizedType pType = (ParameterizedType) type;
final Type[] actualArgs = pType.getActualTypeArguments();
if (actualArgs.length == 0)
throw new IllegalArgumentException("Given method's 1st param type is not parametrized generic: " + method);
Type t = actualArgs[0];
if (t instanceof Class)
return (Class<?>) t;
if (t instanceof TypeVariable){
TypeVariable tv = (TypeVariable) actualArgs[0];
AnnotatedType[] annotatedBounds = tv.getAnnotatedBounds();///
GenericDeclaration genericDeclaration = tv.getGenericDeclaration();///
return (Class) tv.getAnnotatedBounds()[0].getType();
}
throw new IllegalArgumentException("Unknown kind of type: " + t.getTypeName());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.