Background
org.jetbrains.annotations.Contract is a method-level annotation shipped in the org.jetbrains:annotations artifact. It tells IntelliJ-platform IDEs how a method's return value depends on its arguments, and whether the method has side effects. The annotation adds no runtime behavior. It only feeds the IDE's data flow analysis so inspections can warn about NullPointerException, dead code branches, redundant null checks, and ignored return values.
The artifact is bundled with IntelliJ IDEA. For external projects, add a Maven/Gradle dependency on org.jetbrains:annotations (any recent version).
Question
What does each part of @Contract mean, and how is each value constraint used in practice?
Answer
Contract syntax
contract ::= (clause ';')* clause
clause ::= args '->' effect
args ::= ((arg ',')* arg)?
arg ::= value-constraint
value-constraint::= 'any' | 'null' | '!null' | 'false' | 'true'
effect ::= value-constraint | 'fail'
Each clause maps a tuple of argument constraints to an effect on the return value, or to an exception. Multiple clauses are separated with ; and evaluated top-to-bottom.
Value constraints
_ — any value
The argument is unconstrained. Use _ as a placeholder for positions whose value does not influence the clause.
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
@Contract("_, null -> null")
public static @Nullable String pickIfPresent(String fallback, @Nullable String preferred) {
return preferred != null ? preferred : null;
}
// IDE knows the result is null when the second argument is null:
String s = pickIfPresent("x", null);
s.length(); // IDE warning: dereference of null
null — argument is null
The clause applies only when the argument is statically known to be null.
@Contract("null -> null")
public static @Nullable Integer parseOrNull(@Nullable String input) {
if (input == null) return null;
return Integer.parseInt(input);
}
Integer n = parseOrNull(null);
n.intValue(); // IDE warning: n is null
!null — argument is non-null
The clause applies only when the argument is statically known to be non-null.
import org.jetbrains.annotations.NotNull;
@Contract("!null -> !null")
public static @NotNull String upper(@NotNull String s) {
return s.toUpperCase();
}
String result = upper("abc");
if (result == null) { /* IDE warning: condition is always false */ }
true — argument is boolean true
@Contract("true -> fail")
public static void assertFalse(boolean condition) {
if (condition) throw new AssertionError();
}
assertFalse(true);
System.out.println("unreachable"); // IDE warning: unreachable code
false — argument is boolean false
@Contract("false -> fail")
public static void assertTrue(boolean condition) {
if (!condition) throw new IllegalStateException();
}
assertTrue(false);
System.out.println("unreachable"); // IDE warning: unreachable code
Effects
Return value effect
The effect uses the same vocabulary as the argument constraints (null, !null, true, false, _). The effect describes the return value when the argument constraints match.
@Contract("null -> false; !null -> true")
public static boolean isPresent(@Nullable Object value) {
return value != null;
}
if (isPresent(null)) { /* IDE warning: condition is always false */ }
fail — method throws
The method throws an exception when the argument constraints are satisfied. Common in assertions, precondition checks, and requireNonNull-style helpers.
@Contract("null -> fail")
public static void requireNonNull(@Nullable Object value) {
if (value == null) throw new NullPointerException();
}
Object o = null;
requireNonNull(o);
o.toString(); // IDE: o is treated as non-null after this point
Multi-clause contracts
Separate clauses with ;. Each clause is independent; the IDE applies whichever matches the current argument state.
@Contract("_, null -> null; _, !null -> !null")
public static @Nullable String coalesce(String prefix, @Nullable String suffix) {
return suffix == null ? null : prefix + suffix;
}
For methods with multiple arguments, every clause must list a constraint for every parameter, in order.
@Contract("null, _ -> null; !null, null -> !null; !null, !null -> !null")
public static @Nullable String concat(@Nullable String a, @Nullable String b) {
if (a == null) return null;
return b == null ? a : a + b;
}
pure = true
Marks the method as having no visible side effects: no argument mutation, no global state mutation, no I/O. Enables two extra IDE behaviors. First, calls whose return value is unused are flagged. Second, repeated calls with the same arguments are treated as equivalent during data flow analysis.
@Contract(pure = true)
public static int square(int x) {
return x * x;
}
square(5); // IDE warning: result of 'square' is ignored
pure = true may be combined with value:
@Contract(value = "null -> null; !null -> !null", pure = true)
public static @Nullable String identity(@Nullable String s) {
return s;
}
Common patterns
| Pattern | Contract |
|---|---|
| Pass-through nullability | @Contract("null -> null; !null -> !null") |
| Null guard / assertion | @Contract("null -> fail") |
assertTrue |
@Contract("false -> fail") |
assertFalse |
@Contract("true -> fail") |
isNull-style predicate |
@Contract("null -> true; !null -> false") |
| Pure factory |
@Contract(value = "_ -> new", pure = true) (see note below)
|
Note on
new: Thenewreturn-value constraint is supported by IntelliJ IDEA's expanded contract dialect (@Contract(value = "_ -> new", pure = true)) and indicates the method always returns a freshly allocated object. It is not part of the minimal grammar in the annotation Javadoc shown above but is accepted by the platform's analyzer.
Verifying the contract holds
Run code inspections on the file or project. IntelliJ IDEA reports contract violations (for example, a method declared !null -> !null that actually returns null) and uses the declared contract when checking call sites for nullability and unreachable code.
Comments
0 comments
Please sign in to leave a comment.