Author Topic: Java Reflection  (Read 15049 times)

RvK

  • troubleshooter
  • Jackass I
  • Posts: 2
  • Karma: +10/-0
Java Reflection
« on: July 29, 2005, 03:47:22 PM »
Hi all
 

A small FAQ on reflection in JAVA..

 

What is Reflection?

 

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts on objects, within security restrictions. The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class.

 

When to use Reflection?

 

The reflection API's  can be used when we are writing development tools such as debuggers, class browsers, and GUI builders.

 

What can be done with Reflection?

 

With the reflection API you can:

1. Determine the class of an object.
2. Get information about a class's modifiers, fields, methods, constructors, and super classes.
3. Find out what constants and method declarations belong to an interface.
4. Create an instance of a class whose name is not known until runtime.
5. Get and set the value of an object's field, even if the field name is unknown to your program until runtime.
6. Invoke a method on an object, even if the method is not known until runtime.
7. Create a new array, whose size and component types are not known until runtime, and then modify the array's components.

What can not be done with Reflection?
 

You cannot over-ride the Java Security mechanism. For example you cannot access the private methods and variable  
Your Java code is not allowed to perform anything with the reflection API that it couldn't do with static (ordinary, compiled) code
 

What are the classes involved in Reflection?

 

There are three key classes that are involved in the reflection package. They are


java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.Constructor

Field Objects
A Field object represents a reflected field. The underlying field may be a class variable (a static field) or an instance variable (a non- static field). Methods of class Field are used to obtain the type of the underlying field, and to get and set the underlying field's value on objects.

Method Objects
A Method object represents a reflected method. The underlying method may be an abstract method, an instance method, or a class (static ) method.

Methods of class Method are used to obtain the formal parameter types, the return type, and the checked exception types of the underlying method. In addition, the invoke method of class Method is used to invoke the underlying method on target objects. Instance and abstract method invocation uses dynamic method resolution based on the target object's run-time class and the reflected method's declaring class, name, and formal parameter types. (Thus, it is permissible to invoke a reflected interface method on an object that is an instance of a class that implements the interface.) Static method invocation uses the underlying static method of the method's declaring class.

Constructor Objects
A Constructor object represents a reflected constructor. Methods of class Constructor are used to obtain the formal parameter types and the checked exception types of the underlying constructor. In addition, the newInstance method of class Constructor is used to create and initialize a new instance of the class that declares the constructor, provided the class is instantiable.

 

 

An Example with Reflection:

This sample program executes all the getters in any given object and returns a List. The List contains Hashmap which in turn contain name of the method and the value


Code: [Select]
/**

 * @param r The Object whose getter's needs to be invoked

 * @return List of Hashmaps.

 * @author RvK

 */

public static List getValues(Object r) {

List output  = new ArrayList();

            try {

                        Method m[] = r.getClass().getMethods();

Class invokerClass = Class.forName(r.getClass().getName());

Method invoke = null;

Object ret;

HashMap hm = null;

                        for (int i = 0; i < m.length; i++) {

                                    if (m[i].getName().startsWith("get")

                                                            && !m[i].getName().equals("getClass")) {

                                   invoke = invokerClass.getMethod(m[i].getName(), null);

                                   ret = invoke.invoke(r, null);

                                   hm= new HashMap();

                                    hm.put(m[i].getName(),ret);

                                    output.add(hm);                  

                          }

                         }          

                        } catch (Exception e) {

                        e.printStackTrace();

                        }

                        return output;

            }

 

Explanation:

 

The Object method's getClass() method is used to return the name of the Class that the Object belongs. For example if a String is passed in then, r.getClass() will return java.lang.String.
Class.getMethods() will return a list of Methods in the Class.
 

Method.getName() [ Non-static method] Will return the method name. Since we are interested in executing only getters, we filter out the rest. The getClass method is inherited from Class method, so we need to filter that out as well.
 

Then, we obtain a pointer to the method that we are going to invoke from the object using the invokerClass object's getMethod.
 

We invoke the method using invoke method defined in Method Class.
 

The output is added into a hash map and the hash map into a list.
 

Test Case

 
Code: [Select]

public static void main(String[] args) {

                        GetValuesOut input = new GetValuesOut("name","type","value");

                        List obj= ObjectUtil.getValues(input);

                        HashMap hm;

                        for (int i =0;i
                                   hm = (HashMap) obj.get(i);

                                    Iterator it =  hm.keySet().iterator();

                                    while(it.hasNext())

                                    System.out.println(hm.get(it.next()));

                        }

            }

 

GetValuesOut is an  userdefined object. It has 3 methods and the constructor that we invoke above is defined as

 
Code: [Select]

public GetValuesOut(Object name,Object type,Object value){

                        this.name = name;

                        this.type = type;

                        this.value = value;

            }

 

Have fun with Reflection … hope it was useful

RvK
« Last Edit: July 29, 2005, 03:49:05 PM by RvK »
:) Inovation - the Path to Progress :)

incognito

  • In the Abis
  • Jackass IV
  • Posts: 544
  • Karma: +15/-20
Java Reflection
« Reply #1 on: July 29, 2005, 03:54:09 PM »
Nice, article. Interesting how nothing is really private in java. :)