Annotation Improvements

There are couple of improvements made in the annotation mechanism in Java 8. These are:

  1. Repeatable annotations
  2. Type annotations

Code for this section is inside ch12 package.

Repeatable annotations

Before Java 8, it was not possible to use same annotation twice at the same location i.e. you can't use annotation @Foo twice on a method. If you have used JPA then you would have use an annotation called @JoinColumns that allows wraps multiple @JoinColumn annotation as shown below.

@ManyToOne
@JoinColumns({
    @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
    @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
})
public Address getAddress() { return address; }

In Java 8, you can write the same as shown below because with Java 8 you can repeat an annotation multiple time at the same location.

@ManyToOne
@JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
@JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
public Address getAddress() { return address; }

With Java 8 you can use same annotation type multiple times possibly with different arguments at any location(class, method, field declaration) in your Java code.

Writing your own repeatable Annotations

To write your own repeatable annotation you have to do the following:

Step 1: Create an annotation with @Repeatable annotation as shown below. @Repeatable annotation requires you to specify a mandatory value for the container type that will contain the annotation. We will create container annotation in step 2.

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(CreateVms.class)
public @interface CreateVm {
    String name();
}

Step 2: Create a container annotation that holds the annotation.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface CreateVms {
    CreateVm[] value();
}

Now you can use the annotation multiple times on any method as shown below.

@CreateVm(name = "vm1")
@CreateVm(name = "vm2")
public void manage() {
    System.out.println("Managing ....");
}

If you have to find all the repeatable annotations on a method then you can use getAnnotationsByType method that is now available on java.lang.Class and java.lang.reflect.Method. To print all the vm names, you can write code as shown below.

CreateVm[] createVms = VmManager.class.getMethod("manage").getAnnotationsByType(CreateVm.class);
Stream.of(createVms).map(CreateVm::name).forEach(System.out::println);

Type annotations

You can now apply annotations at two more target locations -- TYPE_PARAMETER and TYPE_USE.

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE_PARAMETER})
public @interface MyAnnotation {
}

You can use it like

class MyAnnotationUsage<@MyAnnotation T> {
}

You can also use annotations at type usage as shown below.

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE_USE})
public @interface MyAnnotation {
}

Then you can use them as shown below.

public static void doSth() {
    List<@MyAnnotation String> names = Arrays.asList("shekhar");
}

Analytics


书籍推荐