Reflexão Java: Verificando o tipo do parâmetro do método em tempo de execução

9

Eu preciso verificar se o tipo do primeiro parâmetro do método é List<Class<? extends Exception>> ou não. Alguém pode sugerir uma solução melhor do que compará-lo com uma 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>>")) {
  ...
}

Quero dizer algo assim:

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

Isso verifica se é uma lista ou não. Mas como posso verificar a parte Class<? extends Exception> do tipo?

    
por user1534880 18.07.2012 в 15:58
fonte

4 respostas

5

Tentei o seguinte e parece funcionar:

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

Editar: Ok, para os reais desta vez. Eu só agora percebi que era List<Class<? extends Exception>> e não List<? extends Exception> . Então, essa (espero) solução final deve realmente corresponder a esse caso.

    
por Random Human 18.07.2012 / 16:17
fonte
1

EDITAR:

Q: Como ler o limite superior do argumento do parâmetro?

Por exemplo, usaremos a descrição do método

public void testMethod(Collection<? extends Exception);

Primeiro, devemos acessar o parâmetro do parâmetro de método

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

A partir deste parametrizedType , precisamos obter o argumento:

Type argumentOfargument  parametrizedType.getActualTypeArguments()[0];

Até agora tudo bem, agora precisamos verificar se esse argumentOfargument é um curinga.

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

Neste ponto, temos duas opções para superior:

  return  wildcardArgumentofArgumentType.getUpperBounds()[0]

ou menor:

  return  wildcardArgumentofArgumentType.getLowerBounds()[0]
    
por Damian Leszczyński - Vash 18.07.2012 / 16:19
fonte
0

Acho que após o tipo de eliminação você pode "obter esse tipo de informação".

Se você não sabe como isso funciona, confira a documentação oficial: Eliminação do tipo Java

Em suma, quando o compilador interpreta seu código, ele limpa todas as informações genéricas e as substitui pelos parâmetros limitados ou com Object , se não estiverem vinculados.

Você pode usar o operador instanceof para verificar o tipo Exception .

Editar: Se você quiser verificar um parâmetro antes de realmente chamar o método, tente usar o padrão Proxy. Detalhes aqui: Padrão de proxy

    
por Adam Arold 18.07.2012 / 16:01
fonte
0

Você precisa que ele seja especificamente List<Class<? extends Exception>> ou supertipos (como Collection<Class<? extends Exception>> ou mesmo Object ) O.K.? Eu pergunto porque você menciona isAssignableFrom , que procura por um relacionamento subtipo-supertipo.

Se você está procurando por um relacionamento subtipo-supertipo, então você pode fazer algo parecido com o que o Random Human descreve.

Se você estiver procurando por uma correspondência exata, deverá usar equals : as várias classes e interfaces na API de reflexão especificam definições amigáveis de equals . Por exemplo, ParameterizedType diz :

  

Instâncias de classes que implementam essa interface devem implementar um método equals () que equivale a quaisquer duas instâncias que compartilhem a mesma declaração de tipo genérico e tenham parâmetros de tipo iguais.

Claro, isso requer ter algum exemplo de um parâmetro List<Class<? extends Exception>> cujo tipo você pode obter e executar as comparações equals contra.

(Mas, para ser sincera, a abordagem toString , embora hackea, não parece tão ruim para mim!)

    
por ruakh 18.07.2012 / 16:27
fonte