Search code examples
javabehavior

Why instances of `Class` and `Class<?>` has different behavior where it shouldn't be so?


I've found that:

When I'm using Class<?> to declare variable, getAnnotation acts as:

public <A extends Annotation> A getAnnotation(Class<A> annotationClass)

, but when I'm using Class to declare variable, getAnnotation acts as:

public Annotation getAnnotation(Annotation annotationClass)

, so I couldn't compile code, that uses passed annotation class specific methods.


e.g.: I could compile((Class<?>)clazz).getAnnotation(Human.class).age(), but couldn't compile ((Class)clazz).getAnnotation(Human.class).age(), where clazz is some Class instance, and Human is annotation interface, that have age method.


Solution

  • Your question is very unclear, but I suspect you're running into a raw type.


    JLS — 4.8 Raw Types:

    A raw type is define to be either:

    • The name of a generic type declaration used without any accompanying actual type parameters.
    • Any non-static type member of a raw type R that is not inherited from a superclass or superinterface of R.

    JLS — 4.6 Type Erasure:

    Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables).


    So it's actually that this method:

    public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
    

    is erased to this:

    public Annotation getAnnotation(Class annotationClass)
    

    That's why you can call getAnnotation, but the return type won't be Human, it'll just be Annotation.