2015-02-08 58 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

相關問題