GeeCON Prague 2014*
The moose likes Java in General and the fly likes [newbie] invoking methods within a class (java.lang.reflect) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Java in General
Bookmark "[newbie] invoking methods within a class (java.lang.reflect)" Watch "[newbie] invoking methods within a class (java.lang.reflect)" New topic
Author

[newbie] invoking methods within a class (java.lang.reflect)

Jon Camilleri
Ranch Hand

Joined: Apr 25, 2008
Posts: 660

I'm trying to run a method within a class. The problem is that my logic never seems to get past the if statement. see code below.





Jon
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

Method's toString() method doesn't return the name - it returns much more, including the modifiers, return type and parameters. Check out the getName() method instead.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

You are calling toString on the _methods object which is an array. You probably want to call it on the _m object which is a Method.

Or you could try to do a lookup for the method you want. I am sure this tutorial will show you how.


Steve
Jon Camilleri
Ranch Hand

Joined: Apr 25, 2008
Posts: 660

Steve Luke wrote:You are calling toString on the _methods object which is an array. You probably want to call it on the _m object which is a Method.

Or you could try to do a lookup for the method you want. I am sure this tutorial will show you how.


:) I realized I had that bug, but still haven't found a method for retrieving the methods for the "class" or the "instance of the class" that I want. Anyway thanks, I'll dig more...
:confused:

I'm actually reading the tutorial tutorial:



...and this is my code...



I'm passing






Output:
DEBUG runMethod: forName
DEBUG runMethod: forName
DEBUG runMethod: isAssignableFrom
DEBUG runMethod: isInstance
DEBUG runMethod: getModifiers
DEBUG runMethod: isInterface
DEBUG runMethod: isArray
DEBUG runMethod: isPrimitive
DEBUG runMethod: getSuperclass
DEBUG runMethod: getComponentType
DEBUG runMethod: toString
DEBUG runMethod: getName
DEBUG runMethod: asSubclass
DEBUG runMethod: cast
DEBUG runMethod: desiredAssertionStatus
DEBUG runMethod: getAnnotation
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39053
    
  23
Too difficult a question for us beginners. Moving.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Jon Camilleri wrote:
Steve Luke wrote:You are calling toString on the _methods object which is an array. You probably want to call it on the _m object which is a Method.

Or you could try to do a lookup for the method you want. I am sure this tutorial will show you how.


:) I realized I had that bug, but still haven't found a method for retrieving the methods for the "class" or the "instance of the class" that I want. Anyway thanks, I'll dig more...
:confused:


How about the getMethod(String methodName, Class<?>... argType) lookup?


I'm actually reading the tutorial tutorial:



...and this is my code...




There is something wrong with your brackets there. I see it as:

I am pretty sure that would give an else without an if compile error.


I'm passing



Employee.class.getClass().getClass() ? What Class file do you think you will be passing to the method?

Employee.class is an Object of type Class<Employee> (It is a Class Object which has the information for type Employee). So what happens when you call getClass() on an Object of type Class<Employee>? You get an Object of type Class<Class>. You then call getClass() again, which just gets you another reference to a Class<Class>. The end result is the Class Object you are passing into your method has nothing to do with Employee. It only holds information about the Class type (Class.class).

You then repeat the getClass().getClass() calls inside the method. I think you are a bit 'getClass()' happy. Stop calling that method :-)





Those two arguments mean different things. The first one is the Object whose instance method you want to call, while the second one is an argument that needs to be passed to the method in order to run. Have a look at this code:

If I wanted to call the setName(String) method on emp1 (using reflection) then I would need two Objects:
Object 1: emp1 - The Employee Object whose setName(String) method is to be executed
Object 2: n - The String Object which represents the name I am giving the employee.

So I would call your runMethod(...) like:

You had asked about using static methods in one of your comments. If you are calling a static method, then you do not need an Object to call the method on, which means you can pass in null for the third parameter. Also, if your method does not take any arguments than you can pass in null for the forth parameter. So in the above example, I could call the getCompany() static method like:


Note that the argument list for Method#invoke() is invoke(Object obj, Object... args). The invoke method takes an Object as the instance to call on, and a varargs argument (essentially an array) of Objects for arguments to the method (since a Method may have multiple arguments).


Output:
DEBUG runMethod: forName
DEBUG runMethod: forName
DEBUG runMethod: isAssignableFrom
DEBUG runMethod: isInstance
DEBUG runMethod: getModifiers
DEBUG runMethod: isInterface
DEBUG runMethod: isArray
DEBUG runMethod: isPrimitive
DEBUG runMethod: getSuperclass
DEBUG runMethod: getComponentType
DEBUG runMethod: toString
DEBUG runMethod: getName
DEBUG runMethod: asSubclass
DEBUG runMethod: cast
DEBUG runMethod: desiredAssertionStatus
DEBUG runMethod: getAnnotation
Jon Camilleri
Ranch Hand

Joined: Apr 25, 2008
Posts: 660

Well, I've been through your comments, thank you very much, so I've chopped down the code a bit.
It seems like the actual class methods I am calling are not read.

:confused:



Output (nothing interesting here):
[Rob] removed over 2500 DEBUG lines [/Rob]
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

You're still doing it on line 28: Class _cl = cl.getClass();
Just use cl all over the place, because that's the Class<Employee> object.

Also, next time filter out some of those debug print lines. There are over 2500(!) of those! And you don't even think they're important:
Output (nothing interesting here):

Suffice to say, I removed them. It's not really helpful indeed - they're just the methods from the Class class and its parent (Object).
Jon Camilleri
Ranch Hand

Joined: Apr 25, 2008
Posts: 660

Rob Prime wrote:You're still doing it on line 28: Class _cl = cl.getClass();
Just use cl all over the place, because that's the Class<Employee> object.

Also, next time filter out some of those debug print lines. There are over 2500(!) of those! And you don't even think they're important:
Output (nothing interesting here):

Suffice to say, I removed them. It's not really helpful indeed - they're just the methods from the Class class and its parent (Object).


Oh sorry, I thought they might indicate something to you, and, thanks again for correcting my typos. The code is going through a sample class, now I have to figure out how to return a value, preferably in a way that I can cast it from a generic type to the type returned by the method:

double salaryOfHarry = (double) HelperClassesforClasses.runMethod(_cl, "Salary", harry, null)

Is this possible?

Related links: http://java.sun.com/docs/books/tutorial/reflect/member/fieldValues.html

Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

Jon Camilleri wrote:The code is going through a sample class, now I have to figure out how to return a value, preferably in a way that I can cast it from a generic type to the type returned by the method:

double salaryOfHarry = (double) HelperClassesforClasses.runMethod(_cl, "Salary", harry, null)

Is this possible?

If method Salary returns a double or Double, then yes. Although a) your runMethod needs to return Object (the result from _m.invoke, or something else if there is an exception or no method matches), b) you will need Java 5.0 or up for auto unboxing, and c) your method will not call _m.invoke because args == null.

Although that would still leave the risk of a NullPointerException if your runMethod returns null. It's better to use instanceof:
Jon Camilleri
Ranch Hand

Joined: Apr 25, 2008
Posts: 660

Rob Prime wrote:
Jon Camilleri wrote:The code is going through a sample class, now I have to figure out how to return a value, preferably in a way that I can cast it from a generic type to the type returned by the method:

double salaryOfHarry = (double) HelperClassesforClasses.runMethod(_cl, "Salary", harry, null)

Is this possible?

If method Salary returns a double or Double, then yes. Although a) your runMethod needs to return Object (the result from _m.invoke, or something else if there is an exception or no method matches), b) you will need Java 5.0 or up for auto unboxing, and c) your method will not call _m.invoke because args == null.

Although that would still leave the risk of a NullPointerException if your runMethod returns null. It's better to use instanceof:


Thanks (it's working)

NOTE: It would be helpful if this forum had an option to flag threads with status flags, because when searching for similar posts, I would probably give more importance to 'SOLVED' threads. This flag would be shown in the subject.
 
GeeCON Prague 2014
 
subject: [newbie] invoking methods within a class (java.lang.reflect)