A brief analysis of type annotations in Java8

  • 2020-04-01 03:22:15
  • OfStack

Note: as you know, this feature has been added since java5 and is now widely used in many frameworks to simplify configuration in applications. What is that controversial type annotation? Complex or convenient?

What is a type annotation

Before Java 8, annotations could only be used in declared places, such as classes, methods, and properties. In Java 8, annotations can be applied anywhere, such as:

Create class instance

new @Interned MyObject();

Type mapping
myString = (@NonNull String) str;

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

Throw exception statement
void monitorTemperature() throws @Critical TemperatureException { ... }

It is important to note that type annotations are syntax, not semantics, and do not affect Java compile time, load time, and run time, that is, they are not included when compiled into a class file.

Second, the role of type annotations

Take a look at the following code:


Collections.emptyList().add("One");
int i=Integer.parseInt("hello");
System.console().readLine();

The above code is compiled through, but is running will quote UnsupportedOperationException respectively; A NumberFormatException; NullPointerException, these are runtime errors;

Type annotations are used to support strong type checking in Java programs. With the plug-in check framework, runtime errors can be detected at compile time to improve code quality. This is what type annotations do.

Third, check the framework

Check framework is a third-party tool, and the type annotation effect with Java is 1+1> 2. It can be embedded in the javac compiler, used with ant and maven, or as an eclipse plug-in. The address is http://types.cs.washington.edu/checker-framework/.
Check framework can find where type annotations appear and check, for a simple example:


import checkers.nullness.quals.*;
public class GetStarted {
    void sample() {
        @NonNull Object ref = new Object();
    }
}

Compile the above classes using javac


javac -processor checkers.nullness.NullnessChecker GetStarted.java

Compilation is passed, but if modified to:


@NonNull Object ref = null;

If you don't want to use the Type Annotation to detect errors, you don't need the processor, just javac GetStarted. Java can compile through, which is in the Java 8 with Type Annotation Support version, but not in the Java 5,6, and 7 versions, because the javac compiler doesn't know what @nonnull is, but check framework has a downward compatible solution. The type annotation nonnull is commented with /**/
, as shown in the above example:


import checkers.nullness.quals.*;
public class GetStarted {
    void sample() {
         Object ref = null;
    }
}

The javac compiler ignores comment blocks, but the javac compiler in the check framework also detects nonnull errors.
As you can see from the type annotation +check framework, the runtime error can now be found at compile time.

Iv. About JSR 308

JSR 308 wants to address two issues that arise in the Java 1.5 annotations:

1. Syntactic restrictions on annotations: only annotations can be written in the declared place
2. Semantic limitations of type system: type system cannot prevent all bugs
JSR 308 solves the above two problems by:

1. Expand the syntax of the Java language to allow annotations to appear in more places. Include: method receivers public int size() @readonly {... }), generic parameters, arrays, type conversions, type tests, object creation, type parameter bindings, class inheritance and throws clauses. It's basically a type annotation, which is now a feature of Java 8

2. More powerful annotation handlers can be created by introducing pluggable type systems. The type checker analyzes the source code with a type qualified annotation and generates a warning when it detects errors such as mismatches. It's really just the check framework
There are objections to JSR308, which are more complex and static, for example

@NotEmpty List<@NonNull String> strings = new ArrayList<@NonNull String>()> 

Change to dynamic language
var strings = ["one", "two"]; 

Some agree that, after all, the code is the "most fundamental" document. The annotations included in the code clearly indicate the intent of the code writer. It is the intent information contained in the annotations that is most likely to be lost in other documents when not updated or missing. Also, moving run-time errors to the compile phase not only speeds up the development process, but also saves the time spent checking for bugs during testing.

Five, the summary

Not everyone likes this feature, especially dynamic languages more popular today, fortunately, the Java 8 not saying everyone use this feature, the opposition can not use this feature, and some require a higher quality of code person or company can use JSR 308, code is the "basic" document, after all, I am agree with this sentence. Although the code will increase, it can make your code more expressive. Opinions s on this feature vary from person to person.


Related articles: