14 Replies Latest reply: Nov 5, 2010 5:48 PM by 810879 RSS

    Method call with reflection and primitive types - Problem!

    810879
      Hi there!

      I'm having problems with trying to get a method with reflection that has primitive types as arguments in a dynamic way.
      The problem is this:
      my program tries to call methods dynamically with information he gathered from previous runs.

      example method:
      public class Calculator {
           public float addition(float a, float b) {
                return a + b;
           }
      }
      The gathered information from 1 run with this code:
      new Calculator().addition(3, 4) 
      gives me:

      Class: calculator.Calculator
      Method: addition
      Returnvalue class: java.lang.Float
      Returnvalue : 7.0
      Parameters : java.lang.Float 3.0 java.lang.Float 4.0

      So he gathers this information correctly, but only one problem:
      He sees the class of the parameters as instances of java.lang.Float instead of the primitive type float.
      So if I would try to do this:
      Calculator.class.getDeclaredMethod("addition", new Class[]{java.lang.Float.class, java.lang.Float.class});
      My program would do this dynamically with the information he gathered from above.
      Then I would get this error:
      java.lang.NoSuchMethodException: calculator.Calculator.addition(java.lang.Float, java.lang.Float)
      Because the method is declared with primitive types as parameters and therefore he can't find it.

      So my question is: how can I solve this problem?
      One thing I tried was to in the code of the information gatherer I would see if it's a java.lang.Float
      then I would cast the class to float.class.
      Ofcourse with that solution my above code works perfectly.
      But if the programmer would make the method like this:
           public Float addition(Float a, Float b) {
                return a + b;
           }
      with Float from java.lang.Float then my workaround would not work because he would give me this:
      java.lang.NoSuchMethodException: calculator.Calculator.addition(float, float)
      So to keep things short, I would like to know if there is a way to call methods dynamically with reflection
      and it wouldn't matter if the parameters are primitive types or their wrapper for java.

      I hope you guys can see what my problem is, I found it hard to describe it in words...

      Greetings from Belgium!

      Stijn
      ps: sorry for my bad english, I normally speak dutch
        • 1. Re: Method call with reflection and primitive types - Problem!
          Kayaman
          Use Float.TYPE instead of Float.class, same works for other primitives (Integer.TYPE, Short.TYPE etc.)
          • 2. Re: Method call with reflection and primitive types - Problem!
            810879
            I already tried that.
            But the problem is that the gathered information says that the arguments for the method call are from this type: java.lang.Float

            So when I try Calculator.class.getDeclaredMethod("addition", params});
            Where params is a Class-array filled with the classes gained from the information (in this case two times java.lang.Float.class)
            It would work for a method that has parameters of the type Float but not with a method that requires arguments of the primitive type float.

            So the problem is when my 'information gatherer' gathers information from a method it always sees primitive types as wrapper classes (cause this is how java works I guess).
            And when I would do getDeclaredMethod with the classes I gathered it will always try to find methods with the non primitive types as argument.
            I can easily fix this to let it work with the primitives, but this would cause problems cause the code needs to work for both types of methods. The ones with arguments of primitives types and the once with the wrapper class.
            Hope you know understand what my problem is...
            • 3. Re: Method call with reflection and primitive types - Problem!
              796440
              Kayaman wrote:
              Use Float.TYPE instead of Float.class, same works for other primitives (Integer.TYPE, Short.TYPE etc.)
              Or float.class, int.class, etc.
              • 4. Re: Method call with reflection and primitive types - Problem!
                796440
                user2922236 wrote:
                I already tried that.
                But the problem is that the gathered information says that the arguments for the method call are from this type: java.lang.Float
                It's not clear exactly what your problem is. Can you provide an [url http://sscce.org]SSCCE that shows the problem.

                Just taking a guess here, but you may have run into a common issue. I don't remember the details, but when I've run across it myself, I've had to do a series of if/elses that explicitly handles the primitive types individually, and a final else that captures all reference types.

                EDIT: If I recall, I think the case I was dealing with was something like this:
                if (typeName.equals("int") {
                  clazz = int.class;
                }
                else if typeName.equals("double") {
                  clazz = double.class;
                }
                // ... and so on for the rest of the primitives
                else {
                  clazz = Class.forName(typeName);
                }
                I don't know if this is related to your problem or not. I'm just guessing based on the minimal information you've provided.

                Edited by: jverd on Nov 5, 2010 9:49 AM
                • 5. Re: Method call with reflection and primitive types - Problem!
                  796440
                  On a completely unrelated note, unless you're in a very limited memory environment, you should use double rather than float, as float's precision is fairly awful.
                  • 6. Re: Method call with reflection and primitive types - Problem!
                    810879
                    The problem is that my program doens't know if the method to be called with reflection has arguments of primitive types or with their wrapper class.
                    And from the way I see it, their is no way to know this for sure.
                    So is their a way to call a method that has primitives or their wrapper classes?
                    • 7. Re: Method call with reflection and primitive types - Problem!
                      796440
                      user2922236 wrote:
                      The problem is that my program doens't know if the method to be called with reflection has arguments of primitive types or with their wrapper class.
                      This tells me nothing.

                      Please provide an SSCCE.

                      Also, see my edited reply a few above this one with the code snippet added, and see if it's anything like the issue you're having.

                      Edited by: jverd on Nov 5, 2010 9:52 AM
                      • 8. Re: Method call with reflection and primitive types - Problem!
                        810879
                        I'll try to explain what I'm trying to do (it's hard for me cause I'm only 22years old and my motherlanguage is Dutch).
                        So here goes:

                        What I'm trying to do is run a program, gather information of the program, then use reflection to try and 'replay' the original run of that program.
                        So what I do is the following:
                        I let the program run and while running I gather all the information of method calls.
                        For instance let's say this method was run:
                        public static void main(String[] args) {
                             new Calculator().addition(3, 4);
                        }
                        When this program exists my information gatherer has acquired the following information and has saved it in a text file:

                        Class: calculator.Calculator
                        Method: addition
                        Returnvalue class: java.lang.Float
                        Returnvalue : 7.0
                        Parameters : java.lang.Float 3.0 java.lang.Float 4.0

                        Now I would run another class that opens this text files and tries to 'replay' the original run with the information in the text file.
                        //set up of my method, this is normally generated dynamically so the array and everything would be made from the text file
                        //I just give this as an example so you see how it would build it
                        String aClass = "calculator.Calculator";
                        String aMethod = "addition";
                        Class params[] = {java.lang.Float.class, java.lang.Float.class};
                        Object paramsObj[] = {new Float(3.0), new Float(4.0)};
                        
                        // get the Class
                        Class thisClass = Class.forName(aClass);
                        Object iClass = new Calculator();
                        // get the method
                        Method thisMethod = thisClass.getDeclaredMethod(aMethod, params);
                        // call the method
                        System.out.println(thisMethod.invoke(iClass, paramsObj));
                        But the above code wouldn't work with the method I wrote because the method requires primitive float types and not java.lang.Float.
                        So I would get the exception listed in my first post.
                        I hope you understand it now, it's really hard for me to explain this.
                        The problem actually lies in the fact that while programming a user can use primitive types to declare methods and to make objects but when compiled and run,
                        java puts these primitive types in their wrapper class therefore my information gatherer sees them as java.lang.Float instead of the primitive type float.
                        And that's where my problem lies. Ofcourse you could fix this by casting all wrapper classes to their primitive types.
                        But this library / framework needs to work on other peoples code and therefore I can not be sure if they would implement this method with the primitive types or with the wrapper classes.
                        • 9. Re: Method call with reflection and primitive types - Problem!
                          Kayaman
                          public class MyTest {
                          
                               public static void main(String[] args) throws Exception {
                                    MyTest.class.getDeclaredMethod("addition", Float.TYPE, Float.TYPE);
                               }
                               
                               public float addition(float a, float b) {
                                    return a+b;
                               }
                          }
                          Works perfectly. either with Float.TYPE or float.class.

                          How come your "information gatherer" claims that the method accepts Floats as parameters, when it actually accepts floats?
                          • 10. Re: Method call with reflection and primitive types - Problem!
                            796440
                            user2922236 wrote:
                            I'll try to explain what I'm trying to do (it's hard for me cause I'm only 22years old and my motherlanguage is Dutch).
                            I don't think it's a language problem. Your English is fine. It's more about the information you're providing and not providing.

                            I'm still not understanding your problem. What I'm stuck on is this: You seem to not know ahead of time what types the arguments will be, so you're deciding at runtime which type to use. What exactly is it that you use to determine that the arguments are, say, Float, rather than, say, String or Date?
                            But this library / framework needs to work on other peoples code and therefore I can not be sure if they would implement this method with the primitive types or with the wrapper classes.
                            So, is the problem really just that you can't distinguish primitives from their wrappers--e.g. float vs. Float? Or is it that you have no way of knowing what the arg types will be at all, and if someone decided to use String, you'd be equally as screwed distinguishing String vs. Float as you currently are distinguishing float vs. Float?

                            I've asked for an [url http://sscce.org]SSCCE. Twice. If you can't or won't provide one, I doubt I'll be able to understand your problem.
                            • 11. Re: Method call with reflection and primitive types - Problem!
                              810879
                              I think I know what the problem was.
                              You see I use AspectJ for my information gatherer and the way I used to 'build' the signature of my method to be called was like this:
                              for the method: getDeclaredMethod you need 2 arguments.
                              -The name of the method to be called.
                              -And an array of Class objects that tell what type of parameters the method needs

                              With AspectJ I could easily use thisJoinPointStaticPart.getSignature().getName() to get the name of the method.
                              For the array of Class objects I used thisJoinPoint.getArgs() and from each argument the method received I saved the class of that object in an array.
                              But the problem lies there. Because the arguments are primitive it wraps them in their class wrapper. Like java.lang.Float.
                              So ofcourse when I tried to find the declaredmethod with those arguments supplied it would fail because it doesn't mean that because the arguments are in a wrapper class that the signature of that method uses that wrapper class.
                              for example: you could call Calculator.addition(4,3) and at runtime java would make java.lang.Float objects for 4 & 3.
                              But the method signature in your class can still be like this:
                              public class Calculator {
                                   public float addition(float a, float b) {
                                        return a + b;
                                   }
                              }
                              I now fixed that by actually copying the signature style of the called method.
                              I'm sorry if I couldn't provide you with an SSCCE, I tried to do it with the previous post but it seems I failed :).
                              Anyway, thanks for the help and sorry for the trouble.
                              If I knew this from the beginning I wouldn't have to bother you guys!
                              Have a great weekend!
                              Greetings from Belgium
                              Stijn
                              • 12. Re: Method call with reflection and primitive types - Problem!
                                796367
                                OP, I'm still trying to get what it is you said -- and believe me, it's not the dutch!

                                Maybe it's your Calculator that should be saving operations and data to a file -- instead of AspectJ? Think about it, is this an AspectJ project or is it the Calculator project? IF this is an AspectJ project, then it is no wonder that you could not come up with an SSCCE.
                                • 13. Re: Method call with reflection and primitive types - Problem!
                                  796440
                                  user2922236 wrote:
                                  I think I know what the problem was.
                                  Cool.
                                  You see I use AspectJ for my information gatherer and the way I used to 'build' the signature of my method to be called was like this:
                                  for the method: getDeclaredMethod you need 2 arguments.
                                  -The name of the method to be called.
                                  -And an array of Class objects that tell what type of parameters the method needs

                                  With AspectJ I could easily use thisJoinPointStaticPart.getSignature().getName() to get the name of the method.
                                  For the array of Class objects I used thisJoinPoint.getArgs() and from each argument the method received I saved the class of that object in an array.
                                  But the problem lies there. Because the arguments are primitive it wraps them in their class wrapper. Like java.lang.Float.
                                  That sounds like a shortcoming of AspectJ. Or maybe it was done deliberately for some reason. However, if you have these two methods:
                                  public void foo(Float f) {}
                                  public void foo(float f) {}
                                  and if you use reflection to inspect those methods, you will find that the first has Float.class as its arg and the second has float.class. I'm not sure why AspectJ doesn't make that distinction, or where it gets its signature information from.
                                  I'm sorry if I couldn't provide you with an SSCCE, I tried to do it with the previous post but it seems I failed :).
                                  Did you read the SSCCE link I provided earlier? It explains it pretty nicely, I thought. Although I guess if the source of the trouble was AspectJ, that would preclude the SC part of SSCCE (Self-Contained) anyway.
                                  Anyway, thanks for the help and sorry for the trouble.
                                  No trouble. People come here to help.
                                  • 14. Re: Method call with reflection and primitive types - Problem!
                                    810879
                                    I also think that it's a shortcoming of AspectJ and the problem is indeed in AspectJ.
                                    It just took me some time to figure that out :).
                                    And yes I read your link I just couldn't make up how to do that correctly without giving all my code (both aspects and classes).
                                    Thanks for all the help :)!