2015-02-08 74 views
3

说我有以下代码...如何测试Method是否接受参数类型?

@FunctionalInterface 
static interface MessageFunction<T> { 
    void send(T obj); 
} 

static @interface Message { 
    Class<?> value(); 
} 

static class Foo { 

    @Message(String.class) 
    MessageFunction<String> bass = (string) -> { 
     // Do Stuff 
    }; 
} 

static class MessageManager { 

    Map<Class<?>, MessageFunction<?>> messages = new HashMap<>(); 

    public void register(Object obj) { 

     for (Field field : obj.getClass().getDeclaredFields()) { 
      Message message = field.getAnnotation(Message.class); 
      if (message != null) { 
       MessageFunction<?> function; 

       try { 
        function = (MessageFunction<?>) field.get(obj); 
       } catch (IllegalArgumentException | IllegalAccessException e) { 
        e.printStackTrace(); 
        return; 
       } 

       Method sendMethod; 

       try { 
        // Will this work? 
        sendMethod = function.getClass().getDeclaredMethod("send", Object.class); 
       } catch (NoSuchMethodException | SecurityException e) { 
        e.printStackTrace(); 
        return; 
       } 

       // How do I do something like this? 
       /*if (sendMethod.testParamaters(message.value())) { 
        this.messages.put(message.value(), function); 
       }*/ 
      } 
     } 
    } 
} 

public static void main(String[] args) { 
    MessageManager manager = new MessageManager(); 
    manager.register(new Foo()); 
} 

我反映引用泛型类型的@FunctionalInterface的字段。因为方法参数也是通用的,所以我无法知道它接受哪些参数,因此我必须通过其他方法(注释)传递它。

问题是存在注释值和泛型类型不必匹配,似乎无法检查。如果在注释中列出的类型不会被接收到发送方法中,我不会注册失败。

我怎么去关于这个东西,而实际上并没有调用这个方法。有没有办法?更好的是,尽管我知道它最可能不可能,但是有没有办法知道没有注解的参数类型是什么?

+1

可能的复制[获取运行时泛型类](http://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime)。基本上答案是lambda的“不能完成”。 – Radiodef 2015-02-08 07:26:28

+0

我知道有关在运行时获取泛型类型的其他问题的答案。然而,这些解决方案似乎没有工作时处理一个泛型功能接口的lambda – 2015-02-08 21:43:35

+1

我发现[TypeTools](https://github.com/jhalterman/typetools)提到的是另一个关于堆栈溢出的问题。虽然它不直接解决我所问的问题,但它解决了我的特殊问题。 – 2015-02-09 06:13:47

回答

0

以下只是一个建议,我已经在我的项目中使用了它。但这不是一个完美的解决方案。可能是您可以下载GenericHibernateDao框架的源代码并查看方法“getTypeArguments”的源代码。我觉得它太酷了!

// get a class object for your entity 
Class clazz = ... 
Type type = clazz.getGenericSuperclass(); 
     if (type instanceof ParameterizedType) { 
      Type trueType = ((ParameterizedType)type).getActualTypeArguments()[0]; 
      Class modelClass = (Class) trueType; 
      // Now you can creat an Instance in you generic parameterType 
      Object entity = modelClass.forInstance(); 
     } 
+0

我发现了一些类似堆栈溢出的其他软件,但它不起作用。我认为它是因为所讨论的类不是一个声明的类,而是一个lambda。因此它不能转换为ParameterizedType。 这只是一个基于我的观察,我其实不知道。 – 2015-02-08 17:47:20

0

我在我的一些代码中做了类似的事情这是一段代码。

Method[] meths = actionClass.getMethods(); 
       for (Method meth : meths) { 
        Class<?>[] pTypes = meth.getParameterTypes(); 

        /* 
        * Filter out all methods that do not meet correct 
        * signature. The correct signature for an action method 
        * is: String actionName(HttpServletRequest request) 
        */ 
        //...check for the correct number of params and the correct param type 
        if (pTypes.length != 1 || !HttpServletRequest.class.toString().equals(pTypes[0].toString())) { 
         continue; 
        } else { 
         //...check for return type 
         if (!String.class.toString().equals(meth.getReturnType().toString())) { 
          continue; 
         } 
        } 

        //If you make it here than that means the method 
        //meets the requirements to be a full fledged action. 
        //... 
       } 
+0

这不适用于仿制药 – 2015-02-08 17:49:18

2

尝试TypeTools。首先,您需要获得针对你的register方法里面获得bass的声明类的引用:

Class<?> bassClass = field.getDeclaringClass(); 

然后你可以使用TypeTools解决类型参数T,它提供了MessageFunction :的

Class<?> msgType = TypeResolver.resolveRawArgument(MessageFunction.class, bassClass); 
+0

是的,这已经解决了我的问题。在你的文章发布之前,我确实找到了这个库的链接,不过谢谢你有关如何使用它与示例代码相关的例子。 – 2015-02-10 22:39:21

相关问题