我不知道这是否可以用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的实际值。例如
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反射吗?
答案 0 :(得分:1)
当然,这是可能的。使用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
答案 1 :(得分:0)
我刚做了同样的事情。限于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());
}