Monday, February 21, 2011

Java Reflections

_________________________________________________________

reference links: http://tutorials.jenkov.com/java-reflection/classes.html

Through Java's Reflection API's one can inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time.

It also enables instantiation of new objects, invoke methods and get/set field values using reflection.

list of the topics covered :
>>>>Classes :

Using Java Reflection you can inspect Java classes at runtime.
Before you can do any inspection on a class you need to obtain its java.lang.Class object.

If you know the name of the class at compile time you can obtain a Class object like this:
    Class myObjectClass = MyObject.class
If you don't know the name at compile time, but have the class name as a string at runtime, you can do like this:

String className = ... //obtain class name as string at runtime ;

Class class = Class.forName(className);

When using the Class.forName() method you must supply the fully qualified class name including the class package.

From the classes you can obtain information aboutaother elements of class such as, To access with fully qualified class name :
      Class aClass = ... //obtain Class object. See prev. section
String className = aClass.getName();
(or)
Class aClass = ... //obtain Class object. See prev. section
String simpleClassName = aClass.getSimpleName();

You can access the modifiers of a class via the Class object. The class modifiers are the keywords "public", "private", "static" etc. You obtain the class modifiers like this:

  Class myObjectClass = MyObject.class
int modifiers = aClass.getModifiers();

The modifiers are packed into an int where each modifier is a flag bit that is either set or cleared. You can check the modifiers using these methods in the class java.lang.reflect.Modifier:

    Modifier.isAbstract(int modifiers)
Modifier.isFinal(int modifiers)
Modifier.isInterface(int modifiers)
Modifier.isNative(int modifiers)
Modifier.isPrivate(int modifiers)
Modifier.isProtected(int modifiers)
Modifier.isPublic(int modifiers)
Modifier.isStatic(int modifiers)
Modifier.isStrict(int modifiers)
Modifier.isSynchronized(int modifiers)
Modifier.isTransient(int modifiers)
Modifier.isVolatile(int modifiers)
       Class myObjectClass = MyObject.class
Package package = myObjectClass.getPackage();
       Class myObjectClass = MyObject.class
Class superclass = myObjectClass.getSuperclass();
  • Fields :
    Method[] method = aClass.getFields();
  • Annotations :
     Annotation[] annotations = aClass.getAnnotations();

***************************
>>>>Constructor

Using Java Reflection you can inspect the constructors of classes and instantiate objects at runtime. This is done via the Java class java.lang.reflect.Constructor.

Obtaining Constructor Objects

The Constructor class is obtained from the Class object. Here is an example:

Class aClass = ...//obtain class object
Constructor[] constructors = aClass.getConstructors();

The Constructor[] array will have one Constructor instance for each public constructor declared in the class.

If you know the precise parameter types of the constructor you want to access, you can do so rather than obtain the array all constructors. This example returns the public constructor of the given class which takes a String as parameter:

Class aClass = ...//obtain class object
Constructor constructor = aClass.getConstructor(new Class[]{String.class});

Accessing constructor parameters :
Constructor constructor = ... // obtain constructor - see above
Class[] parameterTypes = constructor.getParameterTypes();

You can instantiate an object like this:

//get constructor that takes a String as argument
Constructor constructor = MyObject.class.getConstructor(String.class);
MyObject myObject = (MyObject)constructor.newInstance("constructor-arg1");
****************
>>>>Fields

Using Java Reflection you can inspect the fields (member variables) of classes and get / set them at runtime. This is done via the Java class java.lang.reflect.Field.

Obtaining Field Objects :

Class aClass = ...//obtain class object
Field[] methods = aClass.getFields();

If you know the name of the field you want to access, you can access it like this:

Class  aClass = MyObject.class
Field field = aClass.getField("someField");

Field Name :

Field field = ... //obtain field object
String fieldName = field.getName();

Field Type:

Field field = aClass.getField("someField");
Object fieldType = field.getType();

Getting and Setting Field Values :

Class  aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);

**************************

>>>>Methods :

Using Java Reflection you can inspect the methods of classes and invoke them at runtime. This is done via the Java class java.lang.reflect.Method.

Obtaining Method Objects:

Class aClass = ...//obtain class object
Method[] methods = aClass.getMethods();
The Method[] array will have one Method instance for each public method declared in the class.
This example below, returns the public method named "doSomething", in the given class which takes a String as parameter:
Class  aClass = ...//obtain class object
Method method = aClass.getMethod("doSomething", new Class[]{String.class}); (or)
Method method = aClass.getMethod("doSomething", null);// method with no parameters

Method Parameters and Return Types:

You can read what parameters a given method takes like this:
Class[] parameterTypes = method.getParameterTypes();

or the return type like this :
Class returnType = method.getReturnType();

Invoking Methods using Method Object:

//get method that takes a String as argument
Method method = MyObject.class.getMethod("doSomething", String.class);
Object returnValue = method.invoke(null, "parameter-value1");

*********************************

>>>>Getters and Setters :

Using Java Reflection you can
1.inspect the methods of classes
2. them at runtime.
3. detect what getters and setters a given class has.

You cannot ask for getters and setters explicitly, so you will have to scan through all the methods of a class and check if each method is a getter or setter.
Here is a code example that finds getter and setters of a class:
-----
public static void printGettersSetters(Class aClass){
Method[] methods = aClass.getMethods();

for(Method method : methods){
if(isGetter(method)) System.out.println("getter: " + method);
if(isSetter(method)) System.out.println("setter: " + method);
}
}

public static boolean isGetter(Method method){
if(!method.getName().startsWith("get")) return false;
if(method.getParameterTypes().length != 0) return false;
if(void.class.equals(method.getReturnType()) return false;
return true;
}

public static boolean isSetter(Method method){
if(!method.getName().startsWith("set")) return false;
if(method.getParameterTypes().length != 1) return false;
return true;
}
-----
*********************************

>>>>Private Fields & Methods :

It is actually possible to access private fields and methods of other classes via Java Reflection.

Note : only works when running the code as a standalone Java application, like you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager.

Accessing Private Fields :

Example class :
public class PrivateObject {

private String privateString = null;

public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
Accessing the private contents using reflect:
PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
  • Notice the use of the method PrivateObject.class.getDeclaredField("privateString"). It is this method call that returns the private field.
  • This method only returns fields declared in that particular class, not fields declared in any superclasses.
  • By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only.

Accessing Private Methods:

Example class :
public class PrivateObject {

private String privateString = null;

public PrivateObject(String privateString) {
this.privateString = privateString;
}

private String getPrivateString(){
return this.privateString;
}
}
Accessing method:
PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
String returnValue = (String)privateStringMethod.invoke(privateObject, null);
System.out.println("returnValue = " + returnValue);
This code example will print out the text "returnValue = The Private Value", which is the value returned by the method getPrivateString() when invoked on the PrivateObject instance created at the beginning of the code sample.

*******************
Ignored contents under the topic :
Annotations

Generics

Arrays

Dynamic Proxies


Dynamic Class Loadin and Reloading