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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11543134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:30:28  来源:igfitidea点击:

Java reflection: Checking the type of the method parameter at runtime

javareflection

提问by user1534880

I need to check that the type of the method first parameter is List<Class<? extends Exception>>or not. Can anybody suggested better solution than comparing it with a String?

我需要检查方法第一个参数的类型是否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>>")) {
  ...
}

I mean something like this:

我的意思是这样的:

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

This check that it is a list or not. But how I can check the Class<? extends Exception>part of the type?

这个检查它是否是一个列表。但是我如何检查Class<? extends Exception>类型的部分?

采纳答案by Random Human

Just tried the following, and it seems to work:

刚刚尝试了以下方法,它似乎有效:

// 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...
  }
}

Edit:Okay, for reals this time. I just nownoticed that it was List<Class<? extends Exception>>and not List<? extends Exception>. So this (hopefully) final solution should actually match that case.

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

回答by Damian Leszczyński - Vash

EDIT:

编辑:

Q: How to read the upper bound from parameter argument ?

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

For example we will use method description

例如我们将使用方法描述

public void testMethod(Collection<? extends Exception);

public void testMethod(Collection<? extends Exception);

First we must access to parameter of method parameter

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

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

From this parametrizedTypewe must get it argument:

由此parametrizedType我们必须得到它的论点:

Type argumentOfargument  parametrizedType.getActualTypeArguments()[0];

So far so good, now we need to check that this argumentOfargumentis an wildcard.

到目前为止一切顺利,现在我们需要检查这argumentOfargument是一个通配符。

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

At this point we have two options for upper :

此时我们有两个 upper 选项:

  return  wildcardArgumentofArgumentType.getUpperBounds()[0]

or for lower :

或更低:

  return  wildcardArgumentofArgumentType.getLowerBounds()[0]

回答by ruakh

Do you need it to be specifically List<Class<? extends Exception>>, or are supertypes (such as Collection<Class<? extends Exception>>, or even Object) O.K.? I ask because you mention isAssignableFrom, which looks for a subtype-supertype relationship.

你需要它是特定的List<Class<? extends Exception>>,还是超类型(例如Collection<Class<? extends Exception>>,甚至Object)可以吗?我问是因为你提到了isAssignableFrom,它寻找子类型-超类型关系。

If you're looking for a subtype-supertype relationship, then you can do something like what Random Human describes.

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

If you're looking for an exact match, then you should be able to use equals: the various classes and interfaces in the reflection API specify friendly definitions of equals. For example, ParameterizedTypesays:

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

Instances of classes that implement this interface must implement an equals() method that equates any two instances that share the same generic type declaration and have equal type parameters.

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

Of course, this requires having some example somewhere of a List<Class<? extends Exception>>parameter whose type you can obtain and perform the equalscomparisons against.

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

(But to be honest, the toStringapproach, while hackish, doesn't look that bad to me!)

(但老实说,这种toString方法虽然有点骇人听闻,但在我看来并没有那么糟糕!)

回答by Adam Arold

I think that after Type Erasure you can'get that kind of information.

我认为在类型擦除之后你可以获得那种信息。

If you don't know about how that works check out the official documentation: Java type erasure

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

In short when the compiler interprets your code it clears all generic information and replaces them with the bounded parameters or with Objectif they are not bound.

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

You can use the instanceofoperator however to check for the Exceptiontype.

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

Edit:If you want to check a parameter before actually calling the method you can try using the Proxy pattern. Details here: Proxy pattern

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