Close

Java 8 Type Annotations

[Last Updated: Sep 2, 2018]

Before Java 8, we can use annotations at many places but only on declarations e.g. on classes, interfaces, fields, method declaration etc. In Java 8 we can generally use annotations on any use of a type, , e.g. with generics, with method return types, with object initiation using 'new', with 'implements' and 'extends' clauses, with type casts and with throws clauses. etc.


New Target ElementType in Java 8

The enum constants provided by java.lang.annotation.ElementType are used in java.lang.annotation.Target meta-annotations to specify where it is legal to write annotations of a given type.

Java 8 introduced two new Element types

  • ElementType.TYPE_USE: allows an annotation to be applied at any type use.
  • ElementType.TYPE_PARAMETER: allows an annotation to be applied at type variables (e.g. T in MyClass<T>).

For example we can now create a new annotation like:

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface MyAnnotation {
}

Usage Examples

extends clause:
public class MyClass extends @MyAnnotation OtherClass { }
implements clause:
public class MyClass implements @MyAnnotation someInterface { }
Generics
public class MyClass<@MyAnnotation T> {}
List<@MyAnnotation String> myList;
List<@MyAnnotation T> myList;
List<@MyAnnotation ? extends OtherClass> myList;
List<@MyAnnotation ? super T> myList
List<@MyAnnotation ?> myList;
Simple Field Types
private @MyAnnotation String str;
private @MyAnnotation List<String> mylist
On arrays
private @MyAnnotation char[] chars; //on char
private @MyAnnotation char[][] chars2;//on char
private char @MyAnnotation [] chars3;//on char array, char[]
private char[] @MyAnnotation [] chars4; //on char array, char[] which is component of char[][]
Nested type
MyClass.@MyAnnotation NestedClass nestedClass;//NestedClass is nested class of MyClass
Creating objects
List<String> list = new @MyAnnotation ArrayList<>();
MyClass myClass = new @MyAnnotation MyClass();
Creating non-static nested class object
MyClass myClass = new @MyAnnotation MyClass();
MyClass.NestedClass nestedClass = myClass.new @MyAnnotation NestedClass();
Type casting
MyClass myClass = (@MyAnnotation MyClass) otherClassInstance;
instanceof
boolean b = myObject instanceof @MyAnnotation OtherClass;
Method return type
public @MyAnnotation String getString(){.....}
Method parameters
public void showString(@MyAnnotation String str){.....}
Calling generic method
myObject.<@MyAnnotation String>myMethod(.....)
Local variables
public void myMethod(){
        @MyAnnotation List<String> str = new ArrayList<>();
}
Java 8 method references
Function<MyClass, String> f = @MyAnnotation MyClass::myMethod;
throws clause
void myMethod() throws @MyAnnotation Exception{}
catch clause
try {
     myObject.myMethod();
  } catch (@MyAnnotation Exception e) {
            .....
 }

In next tutorial we will explore some use cases of type annotations.

See Also