Alignment: Chaotic Java

Friday, December 16, 2005

Reflecting on Generics

To quote the java.lang.reflect package docs (javadocs), "Reflection allows programmatic access to information about the fields, methods and constructors of loaded classes, and the use reflected fields, methods, and constructors to operate on their underlying counterparts on objects, within security restrictions."

Let me just say that I know it doesn't mention generics. It's weird for me too. But you'd expect it would be there, right?

Let us begin. The interface GenericDeclaration (javadoc) comes to describe any Type (javadoc) that can have generics declared on it.

As you'd expect, the class Class (java) (javadoc) implements this interface and it's single method, getTypeParameters. Unfortunately, this method returns only the declaration type. This is of course a result of a thing called Erasure, which is described here (search for "Behind the scenes").

Fine; I understand why Erasure is needed (and unlike what's said in this post, I do understand why it isn't backwards compatible). However, what should I do? While parsing classes in X2J (sourceforge), I need to retrieve the collection's declared type in order to know what type to instanciate when reading an XML file - And I can't, as this information is not stored in the Class instance (and nor in the .class file!)

My solution for now is to add another parameter to the @InnerElement annotation, but it doesn't seem like the best methodoligy..




Why it (dotNet's Generics) backwards compatible: If I'd change one of my inner modules to start using Generics (externally, anyway) in dotNet, I'd have to change an entire application. In Java it won't happen Because of erasure. That way, Sun could make a lot of their older classes generic while retaining backwards compatibility, while in dotNet they created a new namespace for their Collections, which has a different structure than the original (missing classes, different methods, etc). That way, switching to the generic type fo collections in dotNet wasn't as smooth, as they were different classes.

Related Topics
XML to POJOs project in the air
Possible Advantages of X2J -Primary Keys

4 Comments:

At 12/16/2005 06:10:00 PM, Anonymous A.H said...

Shalom Aviad!

I've seen your post @ problogger, and was very suprised to see an israeli guy over there, i think i'm actually the first reader from Israel, started reading there on May...and was suprised from the lack of awareness about this blog in our state.

Well, let me introduce myself:

Allen Heat, from Carmel city in Israel, i hope that maybe in the future we'll have the chance to talk about blogging and money in hebrew :P



Heat

 
At 12/16/2005 06:13:00 PM, Blogger Avah said...

If you think you were surprised, imagine My surprise when I saw someone from Israel coming to my blog from problogger's!

I accept your invitation. How do I get in contact with you?

 
At 12/16/2005 07:43:00 PM, Anonymous Anonymous said...

Although type erasure hides a lot of information, there's still a lot accessible. For example, type parameters that are on a class at compile time (vs. instantiation time) can still be accessed. More applicable to your situation, getters and setters that act on parameterized values retain their generic information! The best way to learn about this stuff is to write a little test class that uses reflection to grab a method and then use a debugger to poke around and see what's available.

The following chunk of code should get you the type of a collection from the getter method:

Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) returnType;
Type actualType = actualType = ptype.getActualTypeArguments()[0];;

if (actualType instanceof Class) {
propertyClass = (Class) actualType;
}
}

-Tim Fennell
http://stripes.mc4j.org

 
At 12/16/2005 07:50:00 PM, Blogger Avah said...

Thank you very much! I didn't know that...

I will start implementing it as soon as I finish with Arrays, which are much simpler (getCompoundClass() from their Class instance and that's it).

Thanks again!

 

Post a Comment

Links to this post:

Create a Link

<< Home