Saturday, September 10, 2016

Java Concurrency in Practice - Chapter 2 - Thread Safety

What is thread safety?

A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.

Thread-safe classes encapsulate any needed synchronization so that clients need not provide their own.

Stateless objects are always thread-safe.

Atomicity

A race condition occurs when the correctness of a computation depends on the relative timing or interleaving of multiple threads by the runtime; in other words, when getting the right answer relies on lucky timing.

Race condition due to common compound actions below:
  • read-modify-write: e.g. hit count incrementing
  • check-then-act: e.g. lazy initialization
To avoid race condition, compound actions need to be atomic. Operations A and B are atomic with respect to each other if, from the perspective of a thread executing A, when another thread executes B, either all of B has executed or none of it has. An atomic operation is one that is atomic with respect to all operations, including itself, that operate on the same state.

Locking

When multiple variables participate in an invariant, they are not independent: the value of one constrains the allowed value(s) of the others. Even if they are atomic references which individually thread-safe, they can't avoid the race condition. To preserve state consistency, update related state variables in a single atomic operation.

Intrinsic locks

Java built-in locking mechanism for enforcing atomicity. synchronized block.

A synchronized block has 2 parts:
  • a reference to an object that will serve as the lock; once a thread acquire this lock, other threads must wait, until the thread releases the lock.
  • a block of code to be guarded by that lock; appear to execute as a single, indivisible unit.
Every Java object can implicitly act as a lock for purposes of synchronization; these built-in locks are called intrinsic locks or monitor locks. Intrinsic locks in Java act as mutexes (or mutual exclusion locks)

The synchronized block can easily make a class thread-safe. Using it carelessly, such as synchronizing the entire method can cause threads congestion which leads to another serious problem, which is the performance problem.

Intrinsic locks are reentrant. If a thread tries to acquire a lock that already holds, the request succeeds. Reentrancy saves us from the deadlock in the situation where a subclass overrides the synchronized method (e.g. doSomething()) of its parent class, then in overridden method subclass calls super.doSomething() method.

Guarding state with locks

For each mutable state variable that may be accessed by multiple threads, all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock.

Every shared, mutable variable should be guarded by exactly one lock. Make it clear to maintainers which lock that is. The fact is any Java object can be the lock object besides the intrinsic lock which is just a convenience so that you need not explicitly create lock objects.

For every invariant that involves more than one variable, all the variables involved in that invariant must be guarded by the same lock.

Liveness and performance

Too much of synchronization can lead to liveness or performance problems such as poor concurrency and poor responsiveness.

Improve concurrency while maintaining thread safety by narrowing the scope of the synchronized block. Not too small; you would not want to divide an operation that should be atomic into more than one synchronized block. But it is reasonable to try to exclude from synchronized blocks long-running operations that do not affect shared states, so that other threads are not prevented from accessing the shared state while the long-running operation is in progress.

Deciding how big or small to make synchronized blocks may require tradeoffs among competing design forces, including safety (which must not be compromised), simplicity, and performance. Resist the temptation to prematurely sacrifice simplicity (potentially compromising safety) for the sake of performance. A reasonable balance can usually be found.

Avoid holding locks during lengthy computations or operations at risk of not completing quickly such as the network or console I/O.

Wednesday, September 7, 2016

Java Concurrency in Practice - Chapter 1 - Introduction

Benefits of threads:

  • Exploiting multiple processors.

    • When properly designed, multithreaded programs can improve throughput by utilizing available processor resources more effectively.
    • On single processor systems, while one thread is blocked/wait for a synchronous event such as I/O operation to complete, the another thread can still run, allow the application make progress.

  • Simplicity of modeling.

    • A program that processes one type of task sequentially is simpler to write, less error-prone, and easier to test than one managing multiple different types of tasks at once. With multi threads available, a complicated, asynchronous workflow can be decomposed into a number of simpler, synchronous workflows each running in a separate thread.

  • Simplified handling of asynchronous events.

    • In a single-threaded application, an I/O block could stall the whole processing. To avoid this problem, single-threaded applications are forced to use non-blocking I/O, which is far more complicated and error-prone than synchronous I/O.

  • More responsive user interfaces.

    • If the code called from the main event loop takes too long to execute, the user interface appears to "freeze" until that code finishes, because subsequent user interface events cannot be processed until control is returned to the main event thread. By assigning the long-running task to a separate thread, the main event thread remains free to process UI events, making UI more responsive.

Risks of threads

  • Safety hazards

    • Safety = nothing bad ever happens.
    • Example: race condition.
    • In the absence of sufficient synchronization, the ordering of operations in multiple threads is unpredictable and sometimes surprising. 

  • Liveness hazards

    • Liveness = something good eventually happens.
    • Example: deadlock, starvation, livelock.
    • A liveness failure occurs when an activity gets into a state such that it is permanently unable to make forward progress.

  • Performance hazards

    • Performance = good thing to happen quickly.
    • Example: poor service time, responsiveness, throughput, resource consumption, scalability.
    • Context switches: when the scheduler suspends the active thread temporarily so another thread can run. The higher number of threads, the higher significant costs for saving and restoring execution context, loss of locality, and CPU time spent scheduling threads instead of running them.
    • The synchronization of shared data can inhibit compiler optimizations, flush or invalidate memory caches, and create synchronization traffic on the shared memory bus.

Saturday, July 9, 2016

Java 8 Lambda Expression

What is Lambda Expression?

Lambda expression is also known as Anonymous Function. A function without the name nor bounded to an identifier.

It is First-class Function. That's mean we can pass the anonymous function as an argument to other functions, return it as a value from other functions, assign it to variables or store it into a data structure.

It models code as data which can be passed around and invoked in the later stage in the other functions.

Why does Java need Lambda?

  • To eliminate the boilerplate code (of using anonymous inner class) in modeling the "code as data" so that it become lightweight, shorter and straight to the point. This is handy when working with libraries and frameworks that are designed to accept callback object which provides nothing but just a function. The typical example is to provide a sole purpose ActionListener to a JButton in Swing framework. 

    button.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
          label.setText(e.getActionCommand() + " is clicked");
       }
    });
    

    Using lambda expression, we can do the same thing in just one line as below.

    button.addActionListener(e -> label.setText(e.getActionCommand() + " is clicked"));
    

  • To gain the advantage of declarative programming. "Declarative Programming - A style of building the structure and elements of computer programs—that expresses the logic of a computation without describing its control flow" - Wikipedia. In short, it is a programming style that describes the what to be achieved and hides the how to accomplish it. For example, prior to Java 8, iteration on a Java Collection has to be done explicitly and each element has to be processed in sequence.

    // for each of the increment of the integer i, start from 0 until we reach the size of list
    for (int i=0; i<list.size(); i++) {
        String e = list.get(i); // get the element from the list
        System.out.println(e); // print the element
    }
    

    Using lambda expression in Java 8, the iteration can be abstracted and done internally by the library.

    // for each element in the list, print the element
    list.forEach((e) -> System.out.println(e));
    

    As you can see, this abstraction makes the code easier to read. No more grandmother's tales. Besides, this abstraction also provides the opportunity to the Java Collections library to manage the control flow more efficiently and better performance by using of reordering of the data, parallelism, short-circuiting, or laziness. All these implementations detail are hidden from the programmer.

  • To be friendly with functional programming. The programmer now has another choice of approach/design to resolve a problem beside object-oriented pattern. The Java Collections framework had adopted the functional design pattern and provides the Streams API which is a good place for the programmer to getting start with functional programming. Furthermore, the idea of stateless and immutable data in functional programming make the program run safely and predictable in the multi-threaded environment. You can find more examples in "Functional programming in Java" section. 

Lambda expression in Java

The lambda expression appears in the form of function. In general, a function is a piece of calculation that takes the input and return an output. The arrow token -> is used to separate the parameter (on the left) and expression body that might return value (on the right). Below are examples of lambda expression in Java. Note, the first four examples are doing the same thing.

// parameter -> expression body
(int x) -> { return x * x; };

// without explicit type information
(x) -> { return x * x; };

// without return syntax and curly bracket
(x) -> x * x;

// without bracket for parameter
x -> x * x;

// without parameter and return value
() -> System.out.println("x");

Lexical Scope

Unlike the inner class, lambda expression does not create a new level of scoping. It is lexically scoped which mean the names (and this) in the lambda expression body are interpreted just as they are in its enclosing environment. Refer to the code example below, see the different and get the idea.

public class HelloWorld {
    
    Runnable inner1 = new Runnable() { // New scope is created
        @Override
        public void run() {
            // "this" refers to inner1 instance itself
            System.out.println(this);
        }
    };
    
    Runnable inner2 = new Runnable() { // New scope is created
        @Override
        public void run() {
            // "toString()" of inner class has shadowed the "HelloWorld.toString()"
            System.out.println(toString());
        }
    };

    // "this" refers to this HelloWorld instance
    Runnable lambda1 = () -> System.out.println(this); 

    // "HelloWorld.toString()"
    Runnable lambda2 = () -> System.out.println(toString());  
    
    public String toString() {
        return "Hello, world!";
    }

    public static void main(String... args) {
        new HelloWorld().inner1.run(); // HelloWorld$1@548c4f57
        new HelloWorld().inner2.run(); // HelloWorld$2@1218025c
        new HelloWorld().lambda1.run(); // Hello, world!
        new HelloWorld().lambda2.run(); // Hello, world!
    }
}

How does Java promote Function to First-Class Citizen?

A programming language supports "first-class function" if it treats the function as the first class citizen. Java is primary object-oriented programming language where a function must reside in an object/class. In order to support the first-class function, Java requires Functional Interface as the type for lambda expression and perform Target Typing to fade out the existence of an object while at the same time only highlight the function of this object.

Functional Interface

Every instance in Java must have a type. Java does not introduce new type such as Function Type for lambda expression due to the challenges of complexities and incompatibility with Java typing system. Instead, Java converts lambda expression to a functional interface type, an interface which only has the single abstract method.

The functional interface is best fit into Java typing system and compatible with all common existing libraries. The existing Java libraries can have benefited from lambda expression without radical change or rewrite.

We can create our own functional interface. By marking the interface class with @FunctionalInterface, the compiler will make sure it fits the requirement of being a functional interface.

We can also make use of the common functional interfaces provided by Java.
  • Function<T, R>: Represents a function that accepts one argument and produces a result.
    e.g. (Integer x) -> x.toString();
  • Consumer<T>: Represents an operation that accepts a single input argument and returns no result.
    e.g. (String x) -> System.out.println(x);
  • Supplier<T>: Represents a supplier of results.
    e.g. () -> "Hello";
  • Predicate<T>: Represents a predicate (boolean-valued function) of one argument.
    e.g. (String x) -> x.equals("X");
  • UnaryOperator<T>: Represents an operation on a single operand that produces a result of the same type as its operand.
    e.g. (Integer x) -> x + 2;
  • BinaryOperator<T>: Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
    e.g. (Integer x, Integer y) -> x + y; 
Besides the basic functiona interfaces above, Java also provides common function interfaces for
  • Primitive specification such as IntFunction<R> that accepts an int-valued argument and produces a result.
    e.g. (int x) -> x.toString(); 
  • Multi arities specification such as BiFunction<T, U, R> that accepts two arguments and produces a result.
    e.g. (String x, Integer y) -> x + y;

Target Typing

The functional interface does not appear in the lambda expression as per the following example. 

() -> "Hello";

Both the Callable and PrivilegedAction are the valid type for lambda expression above, but which one to choose? The answer depends on the expected type in the context (target type) where the lambda expression appears. The lambda expression must appear in the context whose target type is a functional interface. The Java compiler responsible for inferring the target type gives any compilation error if it can't find the target type for a lambda expression. Below are lambda expressions in the different context and the target types are highlighted in yellow.

// Assignment
Consumer<String> c = x -> System.out.println(x);

// Array initializer
IntConsumer[] cc = new IntConsumer[] {
    x -> System.out.println(x + 1),
    x -> System.out.println(x + 2),
    x -> System.out.println(x + 3)
};

// Lambda expression body
Supplier<Consumer<String>> s = () -> (x) -> System.out.println(x);

// Conditional expression
IntFunction<Integer> f = true ? x -> 1 : x -> 2;

// Cast expression
Consumer<String> ccast = (Consumer<String>) (x) -> System.out.println(x);

// Return statement
public Consumer<String> todoLater() {
    return x -> System.out.println(x);
}

The target types for the contexts above are obvious. However, this is not the case for Method argument context. Given the overloaded methods below.

public static void doSomething(Callable r) {
}

public static void doSomething(PrivilegedAction t) {
}

// Method argument - Method overloading
doSomething(() -> "Hello"); // Compilation error: reference to doSomething is ambiguous

Passing a lambda expression into doSomething() method causes compilation error due to the overloaded methods which lead to ambiguous target type; Java compiler does not know exactly which the method is referencing to. The similar case happens to the Generic method. Given the generic method in Example class below.

public static <T> void process(UnaryOperator<T> c) {
}

// Method argument - Type argument inference
Example.process(x -> x + 1); // Compilation error

In this case, the data type for x is ambiguous. It could be String or Integer. Whenever the Java compiler can't figure out the target type, we can help by providing the explicit type information.

// Method argument - Method overloading
doSomething((Callable)() -> "Hello");

// Method argument - Type argument inference
Example.<String>process(x -> x + 1);

What are the Method References?

Method references expression has the same characteristics as the lambda expression. It is encoded in a functional interface instance and requires a target type. However, instead of providing a function body, it just refers to an existing method. In other words, we can promote an existing method to become the first-class function. 

The following code examples are a different kind of method references expression. I put the lambda expression together with the corresponding method reference expression, so you can see the difference and get the idea. Both of them will give the same result.

A static method (ClassName::methodName)

BiFunction<Integer, Integer, Integer> operation = (x, y) -> Integer.sum(x, y); // lambda
BiFunction<Integer, Integer, Integer> operation = Integer::sum; // method reference
operation.apply(1, 2); // 3

An instance method of a particular object (instanceRef::methodName)

List<String> list = Arrays.asList("a", "b");
Predicate<String> condition = (x) -> list.contains(x); // lambda
Predicate<String> condition = list::contains; // method reference
condition.test("a"); // true

A super method of a particular object (super::methodName)

class Person {
    public void print() { System.out.println("Person"); }
}

class Worker extends Person {

    private String name;
    
    public Worker(String name) { this.name = name; }
    
    @Override
    public void print() { System.out.println(name); }
    
    public Runnable parentPrint() {
        return () -> super.print(); // lambda
        return super::print; // method reference
    }
}

Worker worker = new Worker("HauChee");
worker.parentPrint().run(); // "Person"

An instance method of an arbitrary object of a particular type (ClassName::methodName)

Worker worker = new Worker("HauChee");
Consumer<Worker> consume = (w) -> w.print(); // lambda
Consumer<Worker> consume = Worker::print; // method reference
consume.accept(worker); // "HauChee"

A class constructor reference (ClassName::new)

Function<String, Worker> makeWorker = (x) -> new Worker(x); // lambda
Function<String, Worker> makeWorker = Worker::new; // method reference
makeWorker.apply("Lew"); // create worker with name "Lew"

An array constructor reference (TypeName[]::new)

IntFunction<int[]> makeIntArray = (i) -> new int[i]; // lambda
IntFunction<int[]> makeIntArray = int[]::new; // method reference
makeIntArray.apply(10);  // creates an int[10]

Functional programming in Java

Java 8 lambda expression makes functional programming in Java much easier. It gives us another choice of programming style in resolving our problem. Therefore, why not get to know what is it and get a taste of it?

"Functional programming - A style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state (stateless) and mutable data (immutable)." - Wikipedia

High Order Function

A function that takes one or more other functions as its input arguments or returns a function as the result. In the code example below, negate is a high order function that takes a function argument and returns a new function which will negate the function argument result.

Function<Integer, Boolean> isZero = x -> x == 0;
isZero.apply(0); // true

Function<Integer, Boolean> isNegative = x -> x < 0;
isNegative.apply(-1); // true

// High order function
Function<Function<Integer, Boolean>, Function<Integer, Boolean>> negate = (func) -> (x) -> !func.apply(x);

Function<Integer, Boolean> isNotZero = negate.apply(isZero);
isNotZero.apply(0); // false

Function<Integer, Boolean> isPositive = negate.apply(isNegative);
isPositive.apply(-1); // false

In the next section, there are 3 different functional programming techniques are demonstrated in order to resolve the following simple formula.

x * y + z where x = 4, y = 10, z = 3

Function Composition

A technique to composites multiple functions into a function When this function is invoked the complete formula is evaluated and return the result.

Function<Integer, Integer> times10 = x -> x * 10;
Function<Integer, Integer> plus3 = x -> x + 3;

BinaryOperator<Function<Integer, Integer>> compose = (before, after) -> x -> after.apply(before.apply(x));

Function<Integer, Integer> times10plus3 = compose.apply(times10, plus3);
// a function that composites times10 and plus3
times10plus3.apply(4); // 43

// composition API provided by Java
times10.andThen(plus3).apply(4); // 43

Partial Function Application

A technique that partially resolves a portion of the formula and return a new function which carrying the resolved data. When this function is invoked then the rest of the formula portion is evaluated together with the resolved data.

BiFunction<Integer, Integer, Function<Integer, Integer>> partial = (x, y) -> z -> x * y + z;
// 4 * 10 is resolved to 40 first then only plus 3
partial.apply(4, 10).apply(3); // 43

Currying

A technique that takes multiple arguments into evaluating a sequence of functions, each with a single argument. It is like replacing the arguments into the formula one by one and evaluation only happen in the final stage.

Function<Integer, Function<Integer, Function<Integer, Integer>>> curry = x -> y -> z -> x * y + z;
r = curry.apply(4).apply(10).apply(3); // 43

Conclusion

The lambda expression might look weird especially for those who only practice object-oriented programming all the time. However, once we understand the concepts behind, get our hands dirty by trying it out, it can also become one of the useful tool for us in our coding life.



References:
http://www.oracle.com/technetwork/articles/java/architect-lambdas-part1-2080972.html
http://www.oracle.com/technetwork/articles/java/architect-lambdas-part2-2081439.html
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html#overview
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
http://cr.openjdk.java.net/~briangoetz/lambda/sotc3.html
https://dzone.com/articles/java-lambda-expressions-vs
https://dzone.com/articles/why-we-need-lambda-expressions
https://www.smashingmagazine.com/2014/07/dont-be-scared-of-functional-programming/
https://dzone.com/articles/functional-programming-java-8
https://en.wikipedia.org/wiki/Anonymous_function
https://en.wikipedia.org/wiki/First-class_function
https://en.wikipedia.org/wiki/Higher-order_function
https://en.wikipedia.org/wiki/Currying

Monday, March 21, 2016

Repeating Annotation Effect - How to get the correct annotation at runtime

Since Annotation was introduced in Java 5, Java had also provided the Reflection interface, java.lang.reflect.AnnotatedElement which represents an annotated element of the program at runtime. It allows us to get the program element's annotations reflectively. An annotation might not be directly present on a program element. Hence, getter methods in AnnotatedElement help to detect and return the annotation(s) with certain kind of presence.

Moreover, the kind of annotation presence is further expanded when Java 8 introduced Repeating Annotation. And of course, new methods were added onto AnnotatedElement to make sure the caller is able to retrieve the annotation with new kind of presence.

This post describes:
  • Different kind of annotation presence, prior to and since Java 8.
  • Which AnnotatedElement method deals with which kind of annotation presence.
The following annotation types and classes are used for explanation in this post.

Given annotation types below.
@Retention(RetentionPolicy.RUNTIME) // Annotation available at runtime
@Target(ElementType.TYPE) // Target to Class/Interface element only
@Inherited // Inheritable. In this case, annotation is inherited to Subclass
public @interface Alert {
    String name() default "";
}

@Retention(RetentionPolicy.RUNTIME) // Annotation available at runtime
@Target(ElementType.TYPE) // Target to Class/Interface element only
@Inherited // Inheritable. In this case, annotation is inherited to Subclass
public @interface Role {
    String name() default "";
}

Apply annotation onto the Access classes below.
@Role(name = "superadmin")
@Alert(name = "superadmin") 
abstract class Access { // Superclass
}

@Role(name = "staff") // Overrided superclass @Role annotation
class ReadOnlyAccess extends Access { // Subclass
}

Now we will use the methods in AnnotatedElement to retrieve the @Role and @Alert annotation at runtime.

Prior to Java 8

Prior to Java 8, there are no precise terms and descriptions about the annotation presences. However, they are obvious and  not too complicated to be understood. Basically, an annotation could have 2 kinds of presences on a program element.
  • Directly present
  • Present

Directly Present

An annotation is explicitly specified on an element and this annotation is visible or available at runtime. To get the annotation that direct present on an element, we use getDeclaredAnnotation(Class) method.

Class c = ReadOnlyAccess.class;
Role roleDirectPresent = (Role) c.getDeclaredAnnotation(Role.class); // roleDirectPresent = @Role(staff)
Alert alertDirectPresent = (Alert) c.getDeclaredAnnotation(Alert.class); // alertDirectPresent = null
Annotation[] allDirectlyPresent = c.getDeclaredAnnotations(); // allDirectPresent = {@Role(staff)}

We are able to get the @Role(staff) because it is directly specified on the ReadOnlyAccess class element. On the hand, although @Alert is specified on Access class element, and it is inherited to ReadOnlyAccess, but we never able to get it using getDeclaredAnnotation(Class) because it is not direct present on ReadOnlyAccess class element.

Present

An annotation is either directly present on an element or inherited from the element's parent and this annotation is visible or available at runtime. To get the annotation that present on an element, we use getAnnotation(Class) method.

Class c = ReadOnlyAccess.class;
Role rolePresent = (Role) c.getAnnotation(Role.class); // rolePresent = @Role(staff)
Alert alertPresent = (Alert) c.getAnnotation(Alert.class); // aleartPresent = @Alert(superadmin) - inherited
Annotation[] allPresent = c.getAnnotations(); // allPresent = {@Role(staff), @Alert(superadmin)}

By using getAnnotation(Class) method, we not only able to get the annotation @Role(staff) that is directly present on ReadOnlyAccess, we also able to get the annotation @Alert(superadmin) that is inherited from Access class element.

Note: Getting an inherited annotation does not work for all annotated element. For example, it does not works for METHOD element because the getAnnotation(Class) method in java.lang.reflect.Method still getting the annotation that directly present on the method element.

Since Java 8

Started from Java 8, an annotation type supports repeatable. We are now able to specify zero to many annotations with the same annotation type. Now, let enhance our annotation type to be repeatable.

Repeating Annotation

We first create the containing annotation types.
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Alerts {
    Alert[] value(); // to contain an array of Alert annotations
}

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Roles {
    Role[] value(); // to contain an array of Role annotations
}

Then specify the @Repeatable annotation onto the annotation types respectively.
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Alerts.class) // Use @Alerts as container annotation
public @interface Alert {
    String name() default "";
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Roles.class) // Use @Roles as container annotation
public @interface Role {
    String name() default "";
}

A few important notes to take:
  • The containing annotation type must have a method named as "value" and return an array of specific annotation. If not, it will be treated as normal annotation type.
  • The characteristic (such as inheritable, runtime visible, target) of the containing annotation type must consistent with the annotation type that it would like to contain. Failing to do so will cause compilation error at annotation type that takes it as annotation container.

Backward Compatibility

Making an annotation type to support repeatable will not break backward compatibility. In the case where the Access and ReadOnlyAccess class remain the same,
@Role(name = "superadmin")
@Alert(name = "superadmin") 
abstract class Access { // Superclass
}

@Role(name = "staff") 
class ReadOnlyAccess extends Access { // Subclass
}

Despite the @Alert and @Role is now repeatable, but we are still able to get the single annotation using the methods below..
Role roleDirectPresent = (Role) c.getDeclaredAnnotation(Role.class); // roleDirectPresent = @Role(staff)       
Role rolePresent = (Role) c.getAnnotation(Role.class); // rolePresent = @Role(staff)

Note: The @Role(staff) annotation that is specified on the ReadOnlyAccess class element will still override the @Role(superadmin) annotation of it superclass Access. They are never accumulated to become repeating annotation

New Kind of Annotation Presence

Due to the existence of the container annotation, new kinds of annotation presence are introduced. What does the methods in AnnotatedElement can do also become more complicated.
  • Directly Present
  • Indirectly Present
  • Present
  • Associated

Let's specify the repeating annotation in our classes. I will then use the AnnotationElement methods to get the annotation and explain the kind of presence accordingly. You may need to come back to here again when you go through the next sections because the example codes in next section are all talking about getting annotation we have specified here.
@Role(name = "superadmin")
@Alert(name = "superadmin") 
@Alert(name = "superuser") // Repeated @Alert
abstract class Access {
}

@Role(name = "staff")
@Role(name = "guest") // Repeated @Role
class ReadOnlyAccess extends Access {
}

Directly Present

An annotation A is directly present on an element E if E has a RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations or RuntimeVisibleTypeAnnotations attribute, and the attribute contains A. - AnnotatedElement Oracle Doc

Well, it basically maintains the contract prior to Java 8. However, things work differently due to the existence of repeating annotation. Look at the ReadOnlyAccess class, now we have the repeating annotation, in this case, two @Role annotations are specified on it. What we see is two individual @Role annotations but in fact, they are contained in a container annotation @Roles. Decompile the ReadOnlyAccess class and you will find that, Java Compiler had turned them into a container annotation as below.

@Roles(
    value = {
        @Role(name = "staff"),
        @Role(name = "guest")
    }
)
class ReadOnlyAccess extends Access {
}

That's mean, what directly present on the ReadOnlyAccess class element is container annotation @Roles.

Note: We can specify the repeating annotations by using the containing annotation type. After all, it is also a valid annotation type.

Let's try to get the annotation that directly present on ReadOnlyAccess class element. Again, we use the getDeclaredAnnotation(Class) to do that. Have a look on the variable(s) returned from each method call below, they should help you to understand the idea behind.

Class c = ReadOnlyAccess.class;

// roleDirectPresent = null 
// @Role annotation no longer direct present. It is an attribute in container annotation @Roles.
Role roleDirectPresent = (Role) c.getDeclaredAnnotation(Role.class);

// rolesDirectPresent = @Roles({@Role(staff), @Role(guest)})
// @Roles is the container annotation that direct present on the class element.
Roles rolesDirectPresent = (Roles) c.getDeclaredAnnotation(Roles.class);

// alertDirectPresent = null
// @Alert not explicitly present at all.
Alert alertDirectPresent = (Alert) c.getDeclaredAnnotation(Alert.class);

// allDirectPresent = {@Roles({@Role(staff), @Role(guest)})}
Annotation[] allDirectPresent = c.getDeclaredAnnotations();

// allRolesDirectPresent = @Roles({@Role(staff), @Role(guest)})
// New method in AnnotatedElement since Java 8. Get container annotation that is directly present on the class element
Roles[] allRolesDirectPresent = (Roles[]) c.getDeclaredAnnotationsByType(Roles.class);

The getDeclaredAnnotationsByType(Class) is a new method in AnnotatedElement which was introduce since Java 8. It can be used to get annotation that is directly present on an element. It seems working equivalent to getDeclaredAnnotation(Roles.class), but it actually can do more. See the next Indirectly Present section.

Indirectly Present

An annotation A is indirectly present on an element E if E has a RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations or RuntimeVisibleTypeAnnotations attribute, and A 's type is repeatable, and the attribute contains exactly one annotation whose value element contains A and whose type is the containing annotation type of A 's type. - AnnotatedElement Oracle Doc

This is one of the new kinds of annotation presence introduced since Java 8. By using our example code for the explanation, the annotation @Role is indirectly present on a ReadOnlyAccess class element because it is runtime visible, and it resides in the @Roles container annotation which is specified on ReadOnlyAccess.

At first glance on the ReadAccessOnly, it may hard to understand why @Role annotations are not directly present on ReadAccessOnly. They did directly specified on the ReadAccessOnly class element. The reason is what I have described in previous Directly Present section. Whenever more than one repeating annotation specified on an element, Java will use container annotation to host the repeating annotations. Therefore, @Role annotations are indirectly present on ReadAccessOnly class element via container annotation @Roles

The getDeclaredAnnotationByType(Class) method can be used to get the annotations from the container annotation.

// allRoleDirectPresent = {@Role(staff), @Role(guest)}
Role[] allRoleDirectPresent = (Role[]) c.getDeclaredAnnotationsByType(Role.class);

This saves our effort from getting the container annotation first, then look through its value attribute to get the annotations.

Present

An annotation A is present on an element E if either:
  • A is directly present on E; or
  • No annotation of A 's type is directly present on E, and E is a class, and A 's type is inheritable, and A is present on the superclass of E.
AnnotatedElement Oracle Doc

Again, it basically maintains the contract prior to Java 8. The AnnotatedElement methods which able to get annotations that present on an element now also able to get the container annotation which directly present on the element or inherited from the element's parent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// rolePresent = @Role(superadmin)
// An annotation inherited from parent class element.
Role rolePresent = (Role) c.getAnnotation(Role.class);

// rolesPresent = @Roles({@Role(staff), @Role(guest)})
// Container annotation is directly present on class element
Roles rolesPresent = (Roles) c.getAnnotation(Roles.class);

// alertPresent = null
// Not specify in either superclass or subclass.
Alert alertPresent = (Alert) c.getAnnotation(Alert.class);

// alertsPresent = @Alerts({@Alert(superadmin), @Alert(superuser)})
// Container annotation is inherited from parent class element.
Alerts alertsPresent = (Alerts) c.getAnnotation(Alerts.class);

// allPresent = {@Role(staff), @Alerts({Alert(superadmin), @Alert(superuser)})}
Annotation[] allPresent = c.getAnnotations();

The interesting part is at line #3 and #7. The @Role annotation specified on superclass Access is not overridden by the @Roles container annotation specified on subclass ReadOnlyAccess. Well, they are two different annotations in fact. And of course, they will not be accumulated into a container annotation.

Associated

An annotation A is associated with an element E if either:
  • A is directly or indirectly present on E; or
  • No annotation of A 's type is directly or indirectly present on E, and E is a class, and A's type is inheritable, and A is associated with the superclass of E.

Another new kind of annotation presence introduced since Java 8. It covers the broadest annotation presence where an annotation is directly or indirectly present on an element or inherited from the element's parent.

The only method in AnnotatedElement that able to return annotation that associated to an element is getAnnotationsByType(Class).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// roleAssociated = {@Role(staff), @Role(guest)}
// Because @Role is repeatable, hence look through the container annotation and return it value attributes.
Role[] roleAssociated = (Role[]) c.getAnnotationsByType(Role.class);

// rolesAssociated = {@Roles({@Role(staff), @Role(guest)})}
// @Roles container annotation is directly present on class element.
Roles[] rolesAssociated = (Roles[]) c.getAnnotationsByType(Roles.class);

// alertAssociated = {@Alert(superadmin), @Alert(superuser)}
// Because @Alert is repeatable, hence look through the inherited container annotation and return it value attributes.
Alert[] alertAssociated = (Alert[]) c.getAnnotationsByType(Alert.class);

// alertsAssociated = {@Alerts({@Alert(superadmin), @Alert(superuser)})}
// @Alerts container annotation is inhertied from parent class element.
Alerts[] alertsAssociated = (Alerts[]) c.getAnnotationsByType(Alerts.class);

The highlights are at line #3 and #7.

#3 - Because @Role is repeatable, so getAnnotationByType(Role.class) looks through the container annotation @Roles and return all @Role annotations that the container contains. If the container is empty, then it will return the inherited @Role annotation (if any).

#7 - getAnnotationByType(Alert.class) is able to return all @Alert annotation inhertied by the ReadOnlyAccess.

Summary

Creating a repeating annotation type is straightforward, but getting the correct annotation could be a bit complicated. By knowing different kinds of annotation presence, it will help us to get the annotation that we want.

Overview of kind of presence detected by different AnnotatedElement methods - AnnotatedElement Oracle Doc
Kind of Presence
MethodDirectly PresentIndirectly PresentPresentAssociated
TgetAnnotation(Class<T>) X
Annotation[]getAnnotations() X
T[]getAnnotationsByType(Class<T>) X
TgetDeclaredAnnotation(Class<T>) X
Annotation[]getDeclaredAnnotations() X
T[]getDeclaredAnnotationsByType(Class<T>) XX

Besides runtime processing, Java also introduced the javax.lang.model.AnnotatedConstruct interface which represents the annotated source code element and allows us to get the annotation during annotation processing at compile time. The annotation presence terms and concepts are same as the AnnotatedElement. If you are interested in annotation processing, you can learn more from Annotation Processing during Compile Time.

References:
https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/AnnotatedElement.html
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html
https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
https://docs.oracle.com/javase/8/docs/api/javax/lang/model/AnnotatedConstruct.html