A user is interactively debugging his software through an interactions pane in an SDK. However, the user cannot remember what public methods and variables are available to him. One solution would be to have a method in each class that prints out information regarding public methods and variables in the class. However, such a solution might not be feasible because it might require changes to code already written. Furthermore, it is redundant to write this code for each new class. We can however use the Reflection API and gain information on the object. This cuts back on the amount of code that needs to be written and it provides a convenient utility that works on all types of objects.
Note: There is no non-Reflection solution to this problem. Below we elaborate on how we employ Reflection to fulfill our needs:
In objectInfo.java, there are three predominant methods: printFieldInfo, printMethodInfo, and printObjectInfo. These methods locate and print out the object type-properties of each field, each method, and the object itself, respectively. To obtain information on a given object, we need to access its metaobject that contains the metadata. We use Class cls = o.getClass() to obtain a Class object. For any Class object, we can use getName() to obtain the name of the class. We can then check if the object is an array using the isArray() method in Class. We use that to obtain the name of the class that presents the array. We can also obtain the component type of the array using the getComponentType() method, which returns a Class object. Calling getName() to obtain the name of that Class object. If we called getComponentType() on a one-dimensional array of integers we would get the following output:
Object is an array
Array: [I Component Type:int
[I is an encoded name for one-dimensional array of integers. If it were two-dimensional array, we would have an output with two left brackets.
If however the object that was passed to printObjectInfo was not an array, then we can still obtain the name of object’s class using the method getName(). We can obtain the object class’s modifiers using the getModifiers method that returns the modifiers encoded as an int. The Modifier class’s toString method returns a String of modifiers based on the encoded int. Although for this particular scenario we decided to print out all the modifiers, we could have also used the other methods (such as, isFinal(int)) in the Modifier class to see if the int the getModifiers method returns represents a particular modifier.
For a given Class object, we can also obtain information regarding public methods available to a particular instance of the class. We have decided to obtain the method’s information using the printMethodInfo method. The Class object can be queried for public methods that the class declares or inherits using getMethods(). It is also possible to get all the methods a certain class declares using the getDeclaredMethods(). This returns an array of Methods that are declared regardless of the method’s modifiers. A private method can be accessed using the setAccessible(boolean) method. In addition, it is possible to obtain a Method object given a name its parameter types using getMethod(String, Class). The Method objects can be queried for their modifiers, return type, and parameter types using respective function (see code).
Just as we obtained method information for a given object, we can also obtain field information (see code). A Class object can be queried for all public fields as well as all declared fields. For each Field we can also obtain its name, type, and value. The value is obtained using the field’s get method, the object must be passed to the get method so that the get method can retrieve the value from that instance.
We can also obtain information regarding constructors of a class but we leave that until example 2.
The code in this example obtained information on a certain object. We can then use this information and display it to the user for debugging. The obvious benefit of Reflection is that information about an object can be obtained during run-time. Furthermore, using methods of the Reflection API, the object can be altered during run time. For example, we can change the value of a given field at run-time. This kind of functionality would come in handy if the user was debugging and decided to change the value of a certain field in the middle of the process.
We have focused on the benefits of Reflection, but we think it is important to mention that the use of Reflection can increase the running time of the program.
Dennis Sosnoski, http://www-106.ibm.com/developerworks/java/library/j-dyn0603/
Source Code (objectInfo.java)