9

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

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

4 回答 4

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>。所以这个(希望)最终解决方案实际上应该与这种情况相匹配。

于 2012-07-18T14:17:43.423 回答
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;  
}

此时,我们有两个 upper 选项:

  return  wildcardArgumentofArgumentType.getUpperBounds()[0]

或更低:

  return  wildcardArgumentofArgumentType.getLowerBounds()[0]
于 2012-07-18T14:19:29.993 回答
0

我认为在类型擦除之后你不能得到那种信息。

如果您不知道它是如何工作的,请查看官方文档: Java 类型擦除

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

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

编辑:如果您想在实际调用方法之前检查参数,您可以尝试使用代理模式。详细信息:代理模式

于 2012-07-18T14:01:34.757 回答
0

您是否需要它是具体List<Class<? extends Exception>>的,或者超类型(例如Collection<Class<? extends Exception>>,甚至Object)可以吗?我问是因为您提到isAssignableFrom,它寻找子类型 - 超类型关系。

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

如果您正在寻找精确匹配,那么您应该能够使用equals:反射 API 中的各种类和接口指定equals. 例如,ParameterizedType

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

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

(但老实说,这种toString方法虽然很老套,但对我来说并没有那么糟糕!)

于 2012-07-18T14:27:42.373 回答