Michael Scharhag

About Michael Scharhag

Michael Scharhag is a Java Developer, Blogger and technology enthusiast. Particularly interested in Java related technologies including Java EE, Spring, Groovy and Grails.

Java 8 Type Annotations

Lambda expressions are by far the most discussed and promoted feature of Java 8. While I agree that Lambdas are a large improvement I think that some other Java 8 feature go a bit short because of the Lambda hype. In this post I want to show a number of examples from another nice Java 8 feature: Type Annotations.

Type Annotations are annotations that can be placed anywhere you use a type. This includes the new operator, type casts, implements clauses and throws clauses. Type Annotations allow improved analysis of Java code and can ensure even stronger type checking.

In source code this means we get two new ElementTypes for annotations:

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

The enum value TYPE_PARAMETER allows an annotation to be applied at type variables (e.g. MyClass<T>). Annotations with target TYPE_USE can be applied at any type use.

Please note that the annotations from the following examples will not work out of the box when Java 8 is released. Java 8 only provides the ability to define these types of annotations. It is then up to framework and tool developers to actually make use of it. So this is a collection of annotations frameworks could give us in the future. Most of the examples are taken from the Type Annotations specification and various Java 8 presentations.

Simple type definitions with type annotations look like this:

@NotNull String str1 = ...
@Email String str2 = ...
@NotNull @NotBlank String str3 = ...

Type annotations can also be applied to nested types

Map.@NonNull Entry = ...

Constructors with type annotations:

new @Interned MyObject()
new @NonEmpty @Readonly List<String>(myNonEmptyStringSet)

They work with nested (non static) class constructors too:

myObject.new @Readonly NestedClass()

Type casts:

myString = (@NonNull String) myObject;
query = (@Untainted String) str;


class UnmodifiableList<T> implements @Readonly List<T> { ... }

We can use type Annotations with generic type arguments:

List<@Email String> emails = ...
List<@ReadOnly @Localized Message> messages = ...
Graph<@Directional Node> directedGraph = ...

Of course we can nest them:

Map<@NonNull String, @NonEmpty List<@Readonly Document>> documents;

Or apply them to intersection Types:

public <E extends @ReadOnly Composable<E> & @Localized MessageSource> void foo(...) { ... }

Including parameter bounds and wildcard bounds:

class Folder<F extends @Existing File> { ... }
Collection<? super @Existing File> c = ...
List<@Immutable ? extends Comparable<T>> unchangeable = ...

Generic method invocation with type annotations looks like this:

myObject.<@NotBlank String>myMethod(...);

For generic constructors, the annotation follows the explicit type arguments:

new <String> @Interned MyObject()

Throwing exceptions:

void monitorTemperature() throws @Critical TemperatureException { ... }
void authenticate() throws @Fatal @Logged AccessDeniedException { ... }

Type annotations in instanceof statements:

boolean isNonNull = myString instanceof @NonNull String;
boolean isNonBlankEmail = myString instanceof @NotBlank @Email String;

And finally Java 8 method and constructor references:

@Vernal Date::getDay
List<@English String>::size
Arrays::<@NonNegative Integer>sort


Type annotations are an interesting addition to the Java type system. They can be applied to any use of a type and enable a more detailed code analysis. If you want to use Type annotations right now you should have a look at the Checker Framework.

Reference: Java 8 Type Annotations from our JCG partner Michael Scharhag at the mscharhag, Programming and Stuff blog.
Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

Leave a Reply

4 × = thirty two

Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books