The compiler's error messages are confusing purely because it is not laid out to accept such a syntax.
A similar question was already posted here.
Case 1
The JLS, Section 9.6 states the general syntax of an annotation declaration as follows:
AnnotationTypeDeclaration:
{InterfaceModifier} @ interface Identifier AnnotationTypeBody
The token Identifier, in the terms of the JLS, describes the name of the type; be it class, enum, interface or annotation.
An annotation can not be declared with generic types, as these are referred to by the token TypeParameters, which is not included here.
As to why, this leads to
Case 2
Looking into the next item, Section 9.6.1, we spot the restriction of types an annotation can take:
The return type of a method declared in an annotation type must be one of the following, or a compile-time error occurs:
- A primitive type
- String
- Class or an invocation of Class (§4.5)
- An enum type
- An annotation type
- An array type whose component type is one of the preceding types (§10.1).
(some special cases are addressed further below, but are irrelevant to this problem)
These restrictions are what's causing the dejection of your second annotation. It is simply not designed to hold all types of Objects. It cannot even hold the boxed type of a primitive!
Now, back to Case 1 for a bit: Why are generic Annotations a wrong thing in this grammar? Even before any type erasure occurs, your GenericAnnotation can basically be a holder for every type of Object. It is, in the definition of its foo property, exactly the same as your ObjectAnnotation.
Now, the question is, why is that limitation in place? By limiting the values an annotation might contain, you get two advantages: First, all the values are to be compile-time constants. There is no way to get a runtime-dependent value either into or out of an annotation without heavy use of reflection.
This immediately brings one to the second advantage: Nobody will even get the temptation to put impure (side-effecting) code inside annotations which may be loaded at any random point in the applications lifetime. If you could introduce any type of object, their constructors could do any kind of side-effect at a possibly undetectable time, increasing the complexity of debugging if this technique were used.
Or at least, that's what seems the most logical to me, as there is no official word on this from either Sun or their successors that I could find.
Possible Workaround: None
There is, sadly, no simple, expressive and easy workaround to this.
As you cannot place processes into @Annotation-uses, you can not even do something fancy as serializing the object into a byte array using ObjectOutputStream and ByteArrayOutputStream.