Java 8: Class to AnnotatedType

java, java-8

Solution

So I finally got an acceptable understanding of the `AnnotatedType` interface. Here's a working Java 8 example to illustrate one of its uses

public static void main(String[] args) {
    Class<?> fooClass = Foo.class;
    AnnotatedType type = fooClass.getAnnotatedSuperclass();
    System.out.println(type);
    System.out.println(Bar.class == type.getType());
    System.out.println(Arrays.toString(type.getAnnotations()));
    System.out.println(Arrays.toString(type.getDeclaredAnnotations()));
}

public static class Bar {
}

public static class Foo extends @Custom Bar {
}

// So that annotation metadata is available at run time
@Retention(RetentionPolicy.RUNTIME)
// TYPE_USE being the important one
@Target(value = {ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE,
        METHOD, PACKAGE, PARAMETER, TYPE, TYPE_PARAMETER, TYPE_USE}) 
public @interface Custom {
}

This prints

sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@1d44bcfa
true
[@com.testing.Test$Custom()]
[@com.testing.Test$Custom()]

The `AnnotatedType` interface states

`AnnotatedType` represents the potentially annotated use of a type in the program currently running in this VM.

and `Class#getAnnotatedSuperclass()` javadoc states

Returns an `AnnotatedType` object that represents the use of a type to specify the superclass of the entity represented by this `Class` object.

I've made potentially bold in the `AnnotatedType` javadoc because it makes it clear that the type usage doesn't have to be annotated. If you had

public static class Bar {}
...
Bar.class.getAnnotatedSuperclass(); // returns Class instance for java.lang.Object

This is a use case that wasn't possible in Java 7 and lower because you could not annotate type usages (see some examples here). In Java 8, however, you can do

public static class Foo extends @Custom Bar {

where the type `Bar` is used as a super class and its usage is annotated with `@Custom`. It is therefore an `AnnotatedType`. Therefore, `Foo.class.getAnnotatedSuperClass()` will return an `AnnotatedType` instance for that usage.

How can you convert a `Class` to its own `AnnotatedType`? Does that question even make sense?

The question doesn't make sense. This is because a `Class` object holds self-contained metadata about a class. By self-contained, I mean everything that can be deduced from the class' `.class` file (or actual declaration). You cannot deduce any usages of the type anywhere else and therefore it cannot be converted to any `AnnotatedType` for itself.

You can have

public static class Foo extends @Custom Bar {}

public static class Zoom extends @Custom Bar {}

public static class Doing extends @Custom Bar {}

There is an `AnnotatedType` instance for each of the above uses of `Bar`, but which one would you chose to convert a [Bar] `Class` to its own `AnnotatedType`?

Problem

In Java 8, `Class` appears to have gained methods to get an `AnnotatedType` view of its superclasses and its superinterfaces. How can you convert a `Class` to its own `AnnotatedType`? Does that question even make sense? From what I can tell, an `AnnotatedType` has-a `Type`, not is-a `Type`. It's an `AnnotatedElement`, though; it's all very messy. I have searched through the Javadocs to no avail, so far.

Original source