Frustrations with Java Annotations
(note: minor update on 28-Feb-2009, regarding generics)
Lately I have been working intensively with code that deals with Java annotations. That is, not just annotating classes for use by other packages, but writing code that reads such annotations. This is within context of Jackson JSON-processor; latest versions can use annotations to configure details of how Object serialization and deserialization (data binding) work.
I have learnt to appreciate many things with annotations. They work kind of nicely, and the ability to use meta-annotations makes it possible to even build reusable generic annotation processors (although I am not aware of much work in this area -- but I haven't been looking actively). Also, although limitation to literal types (primitives, Strings, Enums, Class literals, arrays of the same) limits things a bit, it is an understandable restriction.
But I have also found couple of major frustrations with annotations. So here's the airing of grievances (yeah, I know, it's not yet even festivus...):
1. Inability to extend annotations
When creating sets of annotations for a library, it would be useful to be able to create "base annotations". Why? For example to:
- check if a given Annotation type extends the base annotation, to easily recognize "my annotations" (if (annotation instanceof MyBaseAnnotation.class) ..."
- define common set of base properties for related annotations, including default values for some
It's worth noting that lack of sub-classing is also frustrating with Enums, which have some similarities to annotation type.
I suspect there may be solid reasons for not allowing sub-classing. But it is unfortunate at any rate.
2. Inability to use null as value
Perhaps more importantly, there is no way to indicate "none" for any value arguments (String, enums or Class value) -- you can't do something like:
@UseClass(null) // illegal, won't compile
(and ditto for default values). So to denote such a missing or non-applicable value, you need to provide a dummy value like "NoClass.class". Yuck. And with Strings you are just out of luck. This is unfortunate, and I don't know why such a limitation is necessary. It would seem logical to allow nulls for values, including default values.
3. Lack of Generics (with Class arguments)
This is not really something annotations fuctionality itself can do much about: but I will list it nonetheless. It is a shame that one can not add typing to Classes. I mean, it's quite different to specify:
than would something like this:
(if that was legal, which it isn't). This of course ties back to the "Why Java Generics Suck" entry from a while ago.