简体   繁体   English

如何测试Method是否接受参数类型?

[英]How can I test if a Method will accept a parameter type?

Say I have the following code... 说我有以下代码......

@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());
}

I am reflecting a field that references an @FunctionalInterface of a generic type. 我正在反映一个引用泛型类型的@FunctionalInterface的字段。 Because the method parameter is also generic I have no way of knowing what parameters it accepts, Thus I must pass it along through other means (the annotation). 因为方法参数也是通用的,所以我无法知道它接受哪些参数,因此我必须通过其他方式(注释)传递它。

The issue is that there is the annotation value and the generic type do not have to match and there seems to be no way to check. 问题是有注释值,泛型类型不必匹配,似乎没有办法检查。 I wan't it to fail in registration if the type listed in the annotation would not be accepted into the send method. 如果注释中列出的类型不会被send方法接受,我就不会注册失败。

How would I go about thing this without actually calling the method. 如果不实际调用方法,我将如何处理这个问题。 Is there a way? 有办法吗? Better yet although I know its most likely impossible, is there a way to know what the parameter type is without the annotation? 更好的是,虽然我知道它很可能是不可能的,但有没有办法知道没有注释的参数类型是什么?

Try TypeTools . 试试TypeTools First you'll need to obtain a reference to the declaring class for the bass which you're obtaining inside of your register method: 首先,你需要获得一个对你在register方法中获得的bass声明类的引用:

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

Then you can use TypeTools to resolve the type argument T that it supplies for MessageFunction: 然后,您可以使用TypeTools来解析它为MessageFunction提供的类型参数T

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

The following is just a suggestion, I have used it in my project. 以下只是一个建议,我在我的项目中使用过它。 But it is not a perfect solution for the question. 但对于这个问题,它并不是一个完美的解决方案。 May be you can download the source of GenericHibernateDao framework and see the sourcecode of method "getTypeArguments". 也许你可以下载GenericHibernateDao框架的源代码并查看方法“getTypeArguments”的源代码。 I think it is so cool!. 我觉得它真酷!

// 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();
        } 

I do something similar in some of my code Here is a snippet. 我在我的一些代码中做了类似的事情。这是一个片段。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM