Java Generics and Reflection

Hi, the other day I had a situation, where in my code at run time I had to determine the super type of the Class that I obtained. To sub type my classes, I used generics.

In case my obtained Class was of expected super type, I had to invoke a super class static method on the subclass Class using reflection.

I used these concepts and prepared a short tutorial, I also attached source files to this post in case someone wants to download them. What I did was I created an abstract class, and an extending child class using generics. In my test client, I determine the super type of my child class at run time and then I invoke a static method using reflection.

Reflection also allows to invoke methods, constructors and change value of fields that are private. It is often called “reflection attack”. In my post Hack any Java class using reflection attack, I give several examples about reflection attack.

Ok, back to the topic now:

My abstract parent class:

[java]
import java.io.Serializable;
import java.util.Date;

public abstract class AbstractParentEntity
<E extends AbstractParentEntity>
implements Serializable {

private static final
long serialVersionUID = 5419258598746186610L;

public static Long getSomeLongValue() {
return new Long(999);
}

}
[/java]

My extending child class:

[java]
import java.io.Serializable;

public class ChildEntity extends
AbstractParentEntity<ChildEntity>
implements Serializable {

private static final long
serialVersionUID = -2271176823058287608L;

private String name;

public ChildEntity() {

}
}
[/java]

My test client:

[java]
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public class Test {

//canonical name of my child class
private static final String
CHILD_CLASS_NAME = "ChildEntity";
//name of the static method i am going to invoke
private static final String
PARENT_METHOD = "getSomeLongValue";

public static void main(String[] args) {

Thread thread = Thread.currentThread();

ClassLoader classLoader =
thread.getContextClassLoader();

try {

//use class loader to create a Class for
//a given class name
Class subclass = Class.forName(CHILD_CLASS_NAME,
true, classLoader);
System.out.println("Subclass canonical name: ["
+ subclass.getCanonicalName() + "]");

//get superclass Class from the subclass
Class superclass = subclass.getSuperclass();
System.out.println("Super class canonical name: ["
+ superclass.getCanonicalName() + "]");

//get the type of subclass
Type subtype = subclass.getGenericSuperclass();
System.out.println("Subclass type: ["
+ subtype.toString() + "]");

//check whether my subclass type starts with
//class name of my super type, if true – my subclass
//is indeed of type of my superclass
if (subtype.toString().startsWith(
superclass.getCanonicalName())) {

System.out.println("Class: [" +
subclass.getSimpleName()
+ "] is type of ["
+ superclass.getSimpleName() + "]");
}

// ‘null’ assumes empty array
Method method = subclass.getMethod(PARENT_METHOD,
(Class[]) null);

/*
* public Object invoke(Object obj, Object args)
*
* If the underlying method is static, then the specified ‘obj’
* argument is ignored. It may be null.
*
* Parameters: obj – the object the underlying method is invoked
* from args – the arguments used for the method call
*/

System.out.println("Invoking static parent method: [" +
PARENT_METHOD + "] on extending subclass…");
Object objResult = method.invoke(null, (Object[]) null);

System.out.println("Some value: [" + objResult.toString() + "]");

}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}

}
}
[/java]

Basically what happens is: iI compare whether the Type of my subclass: AbstractParentEntity starts with the canonical name of my super class: AbstractParentEntity.

When using generics, this will always return true if my subclass extended from my super class.

When I successfully determined the subclass type, i invoked static method using reflection. Below you can see the output of my program:

[java]
Subclass canonical name: [ChildEntity]
Super class canonical name: [AbstractParentEntity]
Subclass type: [AbstractParentEntity<ChildEntity>]
Class: [ChildEntity] is type of [AbstractParentEntity]
Invoking static parent method: [getSomeLongValue] on extending subclass…
Some value: [999]
[/java]

If you never used generics in Java (those who moved on to Java from C++ will know what generics are), Sun offers a nice generics introduction tutorial which explains the basics.

Basically generics allow you to abstract over types. When you use generics in your code it becomes safer and clearer. So i think it worth while having a pick at it :)

Comments / corrections / flames?

 

Comments are closed.