Java反射:在运行时检查方法参数的类型

时间:2012-07-18 13:58:33

标签: java reflection

我需要检查方法第一个参数的类型是否为List<Class<? extends Exception>>。任何人都可以提出比将其与String相比更好的解决方案吗?

Method m = Foo.class.getMethod("m1", List.class);
if (m.getGenericParameterTypes()[0].toString().equals("java.util.List<java.lang.Class<? extends java.lang.Exception>>")) {
  ...
}

我的意思是这样的:

List.class.isAssignableFrom((Class<?>)((ParameterizedType)m.getGenericParameterTypes()[0]).getRawType()));

检查它是否为清单。但是我如何检查类型的Class<? extends Exception>部分?

4 个答案:

答案 0 :(得分:5)

试过以下内容,似乎有效:

// package whatever.your.package.happens.to.be;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.WildcardType;
import java.util.List;

public class ReflectionTest {
  public static void main(String[] args) throws NoSuchMethodException, SecurityException {
    Method method = ReflectionTest.class.getMethod("method", List.class);
    ParameterizedType listType = (ParameterizedType)method.getGenericParameterTypes()[0];
    ParameterizedType classType = (ParameterizedType)listType.getActualTypeArguments()[0];
    WildcardType genericType = (WildcardType)classType.getActualTypeArguments()[0];
    Class<?> genericClass = (Class<?>)genericType.getUpperBounds()[0];

    boolean isException = Exception.class.isAssignableFrom(genericClass);
    // vvv Prints out "Is Class<? extends Exception>: true"
    System.out.println("Is Class<? extends Exception>: " + isException);

    boolean isRuntimeException = RuntimeException.class.isAssignableFrom(genericClass);
    // vvv Prints out "Is Class<? extends RuntimeException>: false"
    System.out.println("Is Class<? extends RuntimeException>: " + isRuntimeException);
  }

  public void method(List<Class<? extends Exception>> exceptionClasses) {
    // Do something with "exceptionClasses," I would imagine...
  }
}

编辑:好的,这次是实时的。我刚刚注意到它是List<Class<? extends Exception>>而不是List<? extends Exception>。所以这个(希望)最终的解决方案应该与这种情况相符。

答案 1 :(得分:1)

编辑:

问:如何从参数参数中读取上限?

例如,我们将使用方法描述

public void testMethod(Collection<? extends Exception);

首先我们必须访问方法参数

的参数
 ParametrizedType parametrizedType = (ParametrizedType)method.getGenericParametersTypes()[0];

从这个parametrizedType我们必须得到它的论点:

Type argumentOfargument  parametrizedType.getActualTypeArguments()[0];

到目前为止,我们需要检查此argumentOfargument是否为通配符。

if(arguemntOfargument instaceof WildcardType) {
   WidlcardType wildcardArgumentofArgumentType = (WidlcardType )argumentOfargument;  
}

此时我们有两个选项:

  return  wildcardArgumentofArgumentType.getUpperBounds()[0]

或更低:

  return  wildcardArgumentofArgumentType.getLowerBounds()[0]

答案 2 :(得分:0)

我认为在Type Erasure之后你可以获得那种信息。

如果您不知道如何运作,请查看官方文档: Java type erasure

简而言之,当编译器解释您的代码时,它会清除所有通用信息并用有界参数替换它们,如果它们没有绑定,则替换为Object

但您可以使用instanceof运算符来检查Exception类型。

编辑:如果要在实际调用方法之前检查参数,可以尝试使用代理模式。详情请见Proxy pattern

答案 3 :(得分:0)

你需要它是专门的List<Class<? extends Exception>>,还是超类型(例如Collection<Class<? extends Exception>>,甚至是Object)O.K。?我问,因为你提到isAssignableFrom,它寻找一个子类型 - 超类型关系。

如果您正在寻找子类型 - 超类型关系,那么您可以执行类似Random Human所描述的内容。

如果您正在寻找完全匹配,那么您应该能够使用equals:反射API中的各种类和接口指定equals的友好定义。例如,ParameterizedType says

  

实现此接口的类的实例必须实现equals()方法,该方法等同于共享相同泛型类型声明且具有相同类型参数的任何两个实例。

当然,这需要在List<Class<? extends Exception>>参数的某个地方设置一些示例,您可以获取其类型并执行equals比较。

(但说实话,toString方法,虽然是hackish,对我来说看起来并不坏!)