@Contract Annotations
In this section:
Overview
The @Contract
annotation brings more safety to your code by defining dependencies between method
arguments and return values. This information provides smarter control flow analysis for the source code and
helps avoid probable errors.
The @Contract
annotation is a powerful and flexible tool that helps make your APIs safer.
Furthermore, it's possible to use it not only for annotating your own code but also for other existing libraries.
Once the annotations are configured for the project libraries, IntelliJ IDEA stores information about the annotations in simple XML files, to share with the team via version control.
To enable the annotations in a project, add <IntelliJ IDEA Home>/lib/annotations.jar
to the classpath via Project Structure dialog.
The usage of @Contract
annotations can be clarified by the following examples:
@Contract("_, null -> null")
- method returnsnull
if its second argument isnull
.@Contract("_, null -> null; _, !null -> !null")
- method returnsnull
if its second argument isnull
, and not-null otherwise.@Contract("true -> fail")
- a typicalassertFalse()
method which throws an exception iftrue
is passed to it.
To learn more about @Contract
annotations, refer to
this page.
Syntax of the @Contract annotation
The @Contract
annotation value has the following syntax:
contract ::= (clause ‘;’)* clause
clause ::= args ‘->’ effect
args ::= ((arg ‘,’)* arg )?
arg ::= value-constraint
value-constraint ::= ‘_’ | ‘null’ | ‘!null’ | ‘false’ | ‘true’
effect ::= value-constraint | ‘fail’
The constraints here are:
_
– any valuenull
– null value!null
– a value statically proved to be not-nulltrue
– true boolean valuefalse
– false boolean valuefail
– the method throws exception, if the arguments satisfy argument constraints
Attributes of the @Contract annotation
The @Contract
annotation has two attributes:
value
and pure
.
The value
attribute contains the contract clauses describing causal relations between call
arguments and the returned value.
The pure
attribute is intended for the methods that do not change the state
of their objects, but just return a new value. This attribute may be used as a hint to the
"Result of method call ignored" inspection to indicate that the method's return value should be used when
called. It is is either false
(by default), or true
.
Example
Consider the following code:
private static void printSorted(){
List <Integer> sorted = Quicksort.sort(null);
if (sorted != null){
System.out.println("Sorted array" + sorted);
}
}
public static <T extends Comparable<T>> List<T> sort(List<T> list){
if(list != null){
List<T> copy = new ArrayList<T>(list);
sort(copy);
return copy;
}
else {
return null;
}
}
IntelliJ IDEA doesn't complain, because it doesn't know that a null input yields a null output.
Let's decorate the sort()
method with @Contract
annotation, specifying that null inputs yield null outputs.
IntelliJ IDEA immediately recognizes that if
statement is extraneous, and reports
about the condition that is always false:
Useful hint
IntelliJ IDEA suggests a quick fix for the methods of the library classes: