Type Annotations: An Added Feature To Annotations In Java 8

Earlier we could only use annotations in Java on declarations. With Java 8, annotations can be written on any use of a type in declarations, generics, and casts. Type annotations are not one of the highlighted features of Java 8. Annotations add more behavior to the piece of code we have written. So type annotation is just an add-on to that, in the sense, that it boosts productivity and ensures higher quality for our code.

For example, if you want to ensure that a particular variable is never assigned to null. You would then modify your code to annotate that particular variable, indicating that it is never assigned to null. The declaration can be like this:

@NonNull String str;

When you compile the code the compiler prints a warning if it detects a defect, which allows you to modify the code if an error is found. After you correct the code to remove all warnings, this particular error will not occur when the program runs.

When we look for tools that make our coding easier and simpler, annotations are never hard to find!

So the question may arise as to why we need type annotations when we already have ordinary annotations to boost efficiency. The simple answer to this is that type annotation allows more errors to be found automatically and gives more control over your tools.

In Java 8, type annotations can be written on any use of a type, such as the following:

@Untainted
String query;
List<@NonNull String> strings;
myGraph = (@Immutable Graph) tmpGraph;

Annotations on types, like annotations on declarations, can be persisted in the class file and made available at run-time via reflection (using the RetentionPolicy.CLASS or RetentionPolicy.RUNTIME policy on the annotation definition). However, there are two primary differences between type annotations and their declaration annotations. First, unlike declaration annotations, type annotations on the types of local variable declarations can be retained in the class files. Second, the full generic type is retained and is accessible at run-time.

In addition to adding annotations on declarations, we can use annotations on the type. By implementing this, we can use tools such as Checker Framework to check and clear software defects that affect the program semantics and thereby boost the overall performance of the code. We should try to explore and make use of these kinds of new techniques to the fullest so that our code would be clean and efficient.