2013-09-11 3 views
0

В моем случае я хочу узнать, включен ли параметр метода для данной реализации GuavaFunction@Nullable. Метод будет реализован:Как получить объект метода для реализации общего интерфейса в Java

boolean isNullableArgument(Class<? extends Function<?,?>> function); 

Я не знаю, как будут реализованы apply метод из function класса.


E.g. там может быть Function реализации, как это:

new Function<String,Integer>() { 
    public Integer apply(String input) { … } 
    public Integer apply(Integer input) { … } 
} 
+1

Я не думаю, что возможная реализация функции, которую вы описываете, на самом деле была бы законной. Ты это пробовал? –

+0

@LouisWasserman Я нашел решение. –

ответ

2

Решение:

import com.google.common.base.Function; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 
import java.lang.reflect.Type; 
import java.lang.reflect.TypeVariable; 
import java.util.Map; 
import javax.annotation.Nullable; 
import org.apache.commons.lang3.reflect.TypeUtils; 

public class FunkUtils { private FunkUtils() {} 

    public static boolean isNullableArgument(Class<? extends Function> functionClass) throws Exception { 
     Map<TypeVariable<?>,Type> typeArgs = TypeUtils.getTypeArguments(functionClass, Function.class); 
     TypeVariable<?> argTypeParam = Function.class.getTypeParameters()[0]; 
     Type argType = typeArgs.get(argTypeParam); 
     Class argClass = TypeUtils.getRawType(argType, null); 
     Method applyMethod = functionClass.getDeclaredMethod("apply", argClass); 
     Annotation[] argAnnos = applyMethod.getParameterAnnotations()[0]; 
     for (int i = 0; i < argAnnos.length; i++) { 
      if (argAnnos[i] instanceof Nullable) return true; 
     } 
     return false; 
    } 
} 

Существует ошибка в TypeUtils.getTypeArguments в Обще-lang3 версии 3.1, но она фиксируется в 3.2, что находится в стадии разработки в настоящее время.

1

Если я получил свой вопрос прямо, вы хотите сделать некоторые проверки в аннотации в методе применения. Вам нужно будет использовать отражение this case (специально this method). Это было бы что-то вроде (я просто сделаю проект, исключающий исключения):

this.getClass().getMethod("apply", parameter.getClass()).getParameterAnnotations() 
+0

Я не думаю, что OP знает, что 'parameter.getClass()' находится во время выполнения. Посмотрите на метод, который они хотят реализовать: 'boolean isNullableArgument (Class > function);'. – Muel

+0

Основная проблема заключается в том, как получить «параметр» из вашего «черновика». –

2

Это быстрое и грязное решение. Не копируйте и не вставляйте его напрямую - это только пример, чтобы вы начали.

static boolean applyHasAnnotation(
     @SuppressWarnings("rawtypes") final Class<? extends Function> functionType, 
     final Class<? extends Annotation> annotationType 
) throws SecurityException, NoSuchMethodException { 
    //for each directly implemented interface, 
    for (final Type interfaceType : functionType.getGenericInterfaces()) { 
     //if the interface is parameterized, 
     if (interfaceType instanceof ParameterizedType) { 
      final ParameterizedType genericInterfaceType = (ParameterizedType)interfaceType; 
      //if the interface is Function 
      if (genericInterfaceType.getRawType() == Function.class) { 
       //get the type argument for T 
       final Type inputType = genericInterfaceType.getActualTypeArguments()[0]; 
       //get its raw type 
       final Class<?> rawInputType = 
         (inputType instanceof ParameterizedType) 
         ? (Class<?>)((ParameterizedType)inputType).getRawType() 
         : (Class<?>)inputType; 
       //use it to find the apply implementation 
       final Method applyMethod = functionType.getDeclaredMethod("apply", rawInputType); 
       //for each annotation on its first (and only) parameter, 
       for (final Annotation inputAnnotation : applyMethod.getParameterAnnotations()[0]) { 
        //if its type is the specified annotation type, return true 
        if (inputAnnotation.annotationType() == annotationType) { 
         return true; 
        } 
       } 
       return false; 
      } 
     } 
    } 
    //a more complicated inheritance hierarchy has defeated us 
    throw new IllegalArgumentException("Function info not found."); 
} 

В действительности, вы хотите, чтобы кодировать различные проблемы отдельно:

  • найти общий интерфейс на реализующего типа
  • глядя вверх F аргумент типа для общего интерфейса
  • , выполняющий поиск apply
  • Проверка его параметров для данной аннотации

Как указано в коде, это решение легко разбивается для более сложных иерархий типов, например:

abstract class LongFunction<T> implements Function<Long, T> { } 

new LongFunction<String> { } бы Function<Long, String>, но вышеупомянутый метод будет не место общего Function интерфейса на его тип времени выполнения.

Смежные вопросы