jeudi 3 mars 2022

How to pass generics in reflecive methods as argument (i.e method.invoke(currClass, GenericClass))

What I am needing is to use reflections to get a class's methods. The method I want to use has a complex type as a parameter, that is unknown at runtime. Using reflections I want to create another Class object that is of this paramter's type. Then call the original class's method with this class object as an argument.

It seems that java does not like me using generics in this fashion. Since it is expecting a argument of a complex type rather than a generic it complains about IllegalArgumentException.

I have tried to simply this algorithm to its core for the sake of making this problem as simple as possible. Assume that a Message may have an unknown number of Complex types and each of those have an unknown number of Complex types within them as well . What I am wanting is to create a method that:

  1. takes in Class object.
  2. Inspects its contents for setMethods.
  3. If current setMethod has a non-primitive as an argument call this method again with the that class type.
  4. When it finds a primitive type use that class's setMethod return this class object.
  5. When we are done inspecting this current Class attempt to pass the returned class into the current class's setMethod that is expecting a complex type.

Step 5 is where I run into issues. Since our method, "Message.setTransactionId" expects an argument of type, "TransactionId", but instead is getting a type Object, or type Class instead I am getting the error, "java.lang.IllegalArgumentException: argument type mismatch"

Problem in simplest form:

    Object nextClass = TransactionId.class;
    Object newClass = Message.class;
    Method[] currentMethods = newClass.getMethods();

    currentMethods[0].invoke(newClass,nextClass);

Little bit more detail:

    public class Message {
        
        private TransactionId myTranactionId;

        public void setTransactionId(TransactionId transactionId){
            myTranactionId = transactionId;
        }
    }

    public class TransactionId{

        private int value;    

        private setValue(int value){
            this.value = value
        }
    }

    public class TestReflections{

        public TestReflections(){

            Class currentTestClass = Message.class;
            parseClass(currentTestClass);
        }

        public class parseClass(Class className){
            int valueToBeAdded = 1;
            Method[] currentMethods = className.getMethods();

            Object nextClass = null;
            Object newClass = className.newInstance();

            for(Method method: currentMethods){
                if(method.getName().startsWith("set")){
                    Class[] methodParams = method.getParameterTypes();
                    if(methodParams[0].isPrimitive()){
                        method.invoke(newClass, valueToBeAdded)
                        return className;
                    }else{
                        nextClass = parseClass(methodParams[0]);
                    }        
                method.invoke(newClass, nextClass);
                return className;
                }
            }
            return className;

        }


    }




Aucun commentaire:

Enregistrer un commentaire