Added
Link Here
|
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 |
<html lang="en"> |
3 |
<head> |
4 |
<meta name="copyright" content="Copyright (c) GK Software AG and others 2014. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." > |
5 |
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
6 |
<meta http-equiv="Content-Style-Type" content="text/css"> |
7 |
<link rel="stylesheet" href="../book.css" charset="ISO-8859-1" type="text/css"> |
8 |
<title>Using null type annotations</title> |
9 |
</head> |
10 |
<body> |
11 |
<h1> Using null type annotations </h1> |
12 |
<p> |
13 |
Starting with Java 8, null annotations can be used in a new and more powerful way, |
14 |
because the new concept of "type annotations" (JSR 308) supports the use of |
15 |
annotations as an extension to the type system. |
16 |
</p> |
17 |
<p> |
18 |
Technically, this is determined by two new elements in |
19 |
the enum <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html" |
20 |
><code>java.lang.annotation.ElementType</code></a>: <code>TYPE_USE</code> and |
21 |
<code>TYPE_PARAMETER</code>. Notably, when saying <code>@Target(ElementType.TYPE_USE)</code> |
22 |
the annotation thus marked can be attached basically to all usages of a type. |
23 |
</p> |
24 |
<p> |
25 |
By interpreting null annotations as part of the type system we interpret each |
26 |
class or interface <code>Cn</code> in the system as introducing two distinct types: |
27 |
"<code>@NonNull Cn</code>" and "<code>@Nullable Cn</code>". |
28 |
The former type contains all instances of <code>Cn</code> whereas the latter type |
29 |
additionally contains the value <code>null</code>. |
30 |
This implies that <code>@NonNull Cn</code> is a subtype of <code>@Nullable Cn</code> |
31 |
with all regular consequences regarding assignability. |
32 |
So ideally for every value in a program we will know if it can be null |
33 |
(and must be checked before dereference) or not. |
34 |
The un-annotated type will be considered a legacy type just like raw types are legacy |
35 |
types since the introduction of generics: a way for interfacing with old code, |
36 |
to be flagged with warnings about unchecked conversions. |
37 |
If we systematically avoid such legacy types, then the compiler can rigorously |
38 |
flag <em>every</em> unsafe usage. |
39 |
</p> |
40 |
<p> |
41 |
In order to achieve completeness of null analysis, checks regarding null type annotations |
42 |
have been integrated with all type checking tasks of the compiler (active if null annotations |
43 |
are enabled). |
44 |
</p> |
45 |
<p> |
46 |
Users <em>migrating</em> from null annotations in previous versions to Java-8-style |
47 |
null type annotations are advised to check the section about <a href="#compatibility">compatibility</a>. |
48 |
</p> |
49 |
|
50 |
<h2 id="generics">Generics</h2> |
51 |
Perhaps the main advantage of type annotations for null analysis is the ability to annotate |
52 |
the parameters and arguments of generic classes and interfaces. |
53 |
Programmers only <em>using</em> generic classes may directly skip to the section on |
54 |
<a href="#typeArguments">type arguments</a> but designers of generic classes should |
55 |
take the time to understand the different implications of annotating these elements: |
56 |
<ul> |
57 |
<li><a href="#typeParameters">type parameters</a></li> |
58 |
<li><a href="#typeVariables">type variables</a></li> |
59 |
<li><a href="#typeArguments">type arguments</a></li> |
60 |
</ul> |
61 |
<h3 id="typeParameters">Type parameters</h3> |
62 |
<p> |
63 |
A generic class, interface or method may <em>declare</em> one or more type parameters. |
64 |
Technically these are declarations, and hence it was a mere oversight that these cannot |
65 |
be annotated in Java 5. |
66 |
In Java 8 an annotation can declare <code>@Target(ElementType.TYPE_PARAMETER)</code> |
67 |
to be applicable in this position. JDT's null type annotations |
68 |
<a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/NonNull.html"><code>@NonNull</code></a> and |
69 |
<a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/Nullable.html"><code>@Nullable</code></a> |
70 |
are declared with |
71 |
<code>@Target({ TYPE_USE })</code>, which includes usage on type parameter declarations. |
72 |
</p> |
73 |
<p> |
74 |
With respect to null type annotations, each type parameter can be specified at one |
75 |
of these levels: |
76 |
</p> |
77 |
<dl> |
78 |
<dt><strong>unconstrained</strong></dt> |
79 |
<dd>the type parameter does not impose any nullness-constraints on the arguments that |
80 |
a client my substitute for the type parameter.</dd> |
81 |
<dt><strong>constrained by an upper bound</strong></dt> |
82 |
<dd>the type parameter has an <code>extends</code> clause that specifies |
83 |
minimal nullness-requirements on type arguments provided by clients</dd> |
84 |
<dt><strong>exactly specified</strong></dt> |
85 |
<dd>the type parameter restricts usage to types of exactly one particular nullness</dd> |
86 |
</dl> |
87 |
<p> |
88 |
Constraining a type parameter via an <strong>upper bound</strong> relies on the fact that each type |
89 |
'<code>@NonNull Cn</code>' is a subtype of the corresponding type '<code>@Nullable Cn</code>'. |
90 |
Hence, a <code>@Nullable</code> upper bound does not impose any restriction, whereas a |
91 |
<code>@NonNull</code> upper bound prohibits the substitution by a <code>@Nullable</code> |
92 |
type argument: |
93 |
<pre> // declarations: |
94 |
class C0<T0 extends @Nullable Object> {} // meaningless, no constraint imposed |
95 |
class C1<T1 extends @NonNull Object> {} |
96 |
... |
97 |
// usage: |
98 |
C1<@NonNull String> c1String; // legal |
99 |
C1<@Nullable String> c1String; // illegal |
100 |
</pre> |
101 |
<p> |
102 |
For <strong>exact specification</strong> a null annotation may be attached to the type parameter |
103 |
declaration itself, which is interpreted as defining both an upper and a lower bound. |
104 |
In other words, only types with the exact same null type annotation are legal as type arguments: |
105 |
</p> |
106 |
<pre> // declaration: |
107 |
class C2<@Nullable T2> {} |
108 |
... |
109 |
// usage: |
110 |
C2<@NonNull String> c2String; // illegal |
111 |
C2<@Nullable String> c2String; // legal |
112 |
</pre> |
113 |
<p> |
114 |
Given the asymmetry, that in Java a type parameter may declare only upper bounds but |
115 |
no lower bounds, the following three styles can be recommended: |
116 |
<ul> |
117 |
<li>Use a <code>@NonNull</code> upper bound for constraining type arguments to nonnull types.</li> |
118 |
<li>Directly specify a type parameter as <code>@Nullable</code> for constraining type arguments to nullable types.</li> |
119 |
<li>Use an unconstrained type parameter to support type arguments of either nullness.</li> |
120 |
</ul> |
121 |
<h3 id="typeVariables">Type variables</h3> |
122 |
<p> |
123 |
Within the scope of a generic declaration (class, interface or method), the name of a |
124 |
type parameter can be used as a <em>type variable</em>, i.e., a placeholder for a type |
125 |
that is not known at this point. |
126 |
</p> |
127 |
<p> |
128 |
A type variable corresponding to a type parameter with a <strong><code>@NonNull</code> upper bound</strong> |
129 |
denotes a type that is <em>known to be nonnull</em>. |
130 |
</p> |
131 |
<pre> class C1<T1 extends @NonNull Number> { |
132 |
int consume(T1 t) { |
133 |
return t.intValue(); // OK: dereference is safe since T1 is known to be nonnull |
134 |
} |
135 |
T1 provide() { |
136 |
return null; // NOT OK: returning null is unsafe since T1 requires nonnull |
137 |
} |
138 |
} |
139 |
</pre> |
140 |
<p> |
141 |
A type variable corresponding to a type parameter <strong>specified as <code>@Nullable</code></strong> |
142 |
denotes a type that is <em>known to be nullable</em>. |
143 |
</p> |
144 |
<pre> class C2<@Nullable T2 extends Number> { |
145 |
int consume(T2 t) { |
146 |
return t.intValue(); // NOT OK: dereference is unsafe since T2 is known to be nullable |
147 |
} |
148 |
T2 provide() { |
149 |
return null; // OK: returning null is safe |
150 |
} |
151 |
} |
152 |
</pre> |
153 |
<p> |
154 |
A type variable corresponding to an <strong>unconstrained</strong> type parameter requires <strong>pessimistic |
155 |
checking</strong> in order to guarantee safety with all legal substitutions: this type can |
156 |
neither be assumed to be nullable nor nonnull. |
157 |
</p> |
158 |
<pre> class C<T extends Number> { |
159 |
int consume(T t) { |
160 |
return t.intValue(); // NOT OK: dereference is unsafe since T could be nullable |
161 |
} |
162 |
T provide() { |
163 |
return null; // NOT OK: returning null is unsafe since T could require nonnull |
164 |
} |
165 |
} |
166 |
</pre> |
167 |
<p> |
168 |
The last point may look surprising at first, but please see that an unconstrained type parameter |
169 |
implies that we may not assume anything about the nullness of the type represented by |
170 |
the corresponding type variable. Even more: we must actively support nullable <em>and</em> |
171 |
nonnull types. On the other hand this simply extends the existing rule that the only |
172 |
type being compatible with an unbounded type variable is the type variable itself. |
173 |
To explain this situation in the context of null analysis, the compiler will raise the |
174 |
following error against the return in <code>provide()</code>: |
175 |
</p> |
176 |
<blockquote> |
177 |
Null type mismatch (type annotations): 'null' is not compatible to the free type variable 'T' |
178 |
</blockquote> |
179 |
<p> |
180 |
By enforcing this defensive strategy regarding unconstrained type parameters we obtain the benefit |
181 |
of allowing clients to freely choose the rules for a particular generic instantiation, |
182 |
as will be shown next. |
183 |
</p> |
184 |
<h3 id="typeArguments">Type arguments</h3> |
185 |
<p> |
186 |
When instantiating a generic type or when invoking a generic method, the constraints put |
187 |
forward by the type parameter must be observed. Hence, when a provider of a generic type or method |
188 |
specified the required nullness, this must be obeyed and the compiler will flag any violations. |
189 |
</p> |
190 |
<p> |
191 |
When, on the other hand, a type parameter does not impose any restrictions, a client may |
192 |
freely choose the nullness of his type arguments: |
193 |
<pre> |
194 |
int processWithoutNulls (@NonNull List<<strong>@NonNull Integer</strong>> ints) { |
195 |
int result = 0; |
196 |
for (int i = 0; i < ints.size(); i++) { |
197 |
Integer element = ints.get(i); |
198 |
result += element.intValue(); // OK: list element is known to be nonnull |
199 |
ints.set(i, null); // NOT OK: list does not accept null value |
200 |
} |
201 |
return result; |
202 |
} |
203 |
int processWithNulls (@NonNull List<<strong>@Nullable Integer</strong>> ints) { |
204 |
int result = 0; |
205 |
for (int i = 0; i < ints.size(); i++) { |
206 |
Integer element = ints.get(i); |
207 |
result += element.intValue(); // NOT OK: list element can be null |
208 |
ints.set(i, null); // OK: list accepts null value |
209 |
} |
210 |
return result; |
211 |
} |
212 |
</pre> |
213 |
|
214 |
<h2 id="inference">Inference</h2> |
215 |
<p> |
216 |
With null type annotations affecting type arguments, the language features one |
217 |
more location amenable to inference: during type inference for the invocation |
218 |
of a generic method (lambda expression etc.), type inference shyly attempts to |
219 |
also infer the appropriate null type annotations. Example: |
220 |
</p> |
221 |
<pre> <T> T check(T in) { return in; } |
222 |
void test(@NonNull List<@Nullable String> someStrings) { |
223 |
@NonNull List<@Nullable String> checked; |
224 |
checked = check(someStrings); // inferring types for this invocation |
225 |
... |
226 |
} |
227 |
</pre> |
228 |
<p> |
229 |
In this trivial example, inference will indeed instantiate the generic parameter <code><T></code> |
230 |
to <code>@NonNull List<@Nullable String></code>. More complex scenarios are inferred, too, |
231 |
but no guarantee is made, that a possible solution will always be found. In that case users |
232 |
are advised to revert to explicitly specify type arguments even of a generic method invocation. |
233 |
</p> |
234 |
|
235 |
<h2 id="more_locations">More locations</h2> |
236 |
<h3>Cast and instanceof</h3> |
237 |
<p> |
238 |
Syntactically, type annotations can be used also in casts and instanceof expressions. |
239 |
For null annotations, however, this has limited value. |
240 |
</p> |
241 |
<p> |
242 |
<strong>Casting</strong> to a null-annotated type is always an <em>unchecked cast</em> because the |
243 |
compiler is not allowed to insert runtime checks that would make the cast meaningful. |
244 |
If a runtime check is desired, please consider using a small helper function like: |
245 |
</p> |
246 |
<pre> static @NonNull <T> T castToNonNull(@Nullable T value, @Nullable String msg) { |
247 |
if (value == null) throw new NullPointerException(msg); |
248 |
return value; |
249 |
} |
250 |
</pre> |
251 |
<p> |
252 |
Casts affecting the type arguments of a generic type will always be unchecked casts due to erasure. |
253 |
</p> |
254 |
<p> |
255 |
<strong>instanceof</strong> checks with null type annotations are not meaningful. |
256 |
Hence the compiler flags this as illegal usage of a null type annotation. |
257 |
</p> |
258 |
<h3>Locations that are nonnull by definition</h3> |
259 |
<p> |
260 |
Syntactically, type annotations can also be used for |
261 |
</p> |
262 |
<ul> |
263 |
<li>allocation expressions</li> |
264 |
<li>method receiver (pseudo argument by the name of <strong>this</strong>)</li> |
265 |
<li>catch parameter</li> |
266 |
</ul> |
267 |
<p> |
268 |
In each of these constructs, the type is nonnull by definition. |
269 |
Hence a null type annotation in one of these positions is flagged as illegal use. |
270 |
This doesn't, however, restrict the use of null type annotations on type arguments |
271 |
of the given type. |
272 |
</p> |
273 |
|
274 |
<h2 id="compatibility">Compatibility</h2> |
275 |
<p> |
276 |
Migrating from declaration annotations to type annotations has a few unavoidable |
277 |
implications, regarding the syntax, regarding project configuration and regarding |
278 |
the semantics. |
279 |
</p> |
280 |
<h3 id="compatibility_syntax">Syntax</h3> |
281 |
<p> |
282 |
For two constructs the JLS introduces a syntactic change: |
283 |
</p> |
284 |
<table border="1" cellspacing="0" cellpadding="5" summary="Syntax Changes"> |
285 |
<tr><th>Declaration Annotations (Java 7 or below)</th><th>Type Annotation (Java 8)</th></tr> |
286 |
<tr><td><code>@NonNull String[]</code></td><td><code>String @NonNull[]</code></td></tr> |
287 |
<tr><td><code>@NonNull java.lang.String</code></td><td><code>java.lang.@NonNull String</code></td></tr> |
288 |
</table> |
289 |
<p> |
290 |
In both cases the new syntax has been introduced to provide more options. |
291 |
</p> |
292 |
<p> |
293 |
For <strong>arrays</strong> a type annotation before the leaf element type will now denote |
294 |
an array whose individual cells have the given nullness - here: cells cannot be null. |
295 |
In Java 7 and below the same syntax expressed a property of the corresponding variable |
296 |
and hence captured the nullness of the array itself. |
297 |
To express the same using Java-8 type annotations, viz. that the array itself can or cannot be null, |
298 |
the type annotation is placed before the square brackets denoting the array dimensions. |
299 |
This implies that the old syntax is still valid, but its meaning has changed: |
300 |
</p> |
301 |
<pre> |
302 |
// annotated leaf type: |
303 |
@NonNull Object [] o1; |
304 |
o1 = null; // OK |
305 |
o1 = new Object[1]; |
306 |
o1[0] = null; // NOT OK |
307 |
... |
308 |
// annotated array type: |
309 |
Object @NonNull[] o2; |
310 |
o2 = null; // NOT OK |
311 |
o2 = new Object[1]; |
312 |
o2[0] = null; // OK |
313 |
... |
314 |
// multi-dimensional array: |
315 |
Object @NonNull[] @Nullable[] o3; |
316 |
o3 = null; // NOT OK, outer array is nonnull |
317 |
o3 = new Object[1] @Nullable[]; |
318 |
o3[0] = null; // OK, inner array is nullable |
319 |
</pre> |
320 |
<p> |
321 |
Unfortunately, checking proper initialization of an array with nonnull content |
322 |
is beyond the capabilities of JDT's static analysis. |
323 |
</p> |
324 |
<p> |
325 |
For <strong>qualified type names</strong> the type annotation must be placed directly preceding the |
326 |
actual type name. This way it is possible to give different type annotations for |
327 |
inner classes and their enclosing like in <code>org.project.@Immutable Outer.@Nullable Inner</code>. |
328 |
This distinction, however, is not useful for null annotations, because the enclosing |
329 |
of a non-static inner class is by definition always non-null. Users of null type |
330 |
annotations only need to understand that the old syntax for this case is illegal |
331 |
for type annotations and how to convert this into legal Java 8 code (see the table above). |
332 |
</p> |
333 |
<h3 id="compatibility_configuration">Project configuration</h3> |
334 |
<p> |
335 |
Properly designed annotation types can be distinguished by looking at their <code>@Target</code> |
336 |
declaration (the use of null annotations lacking a <code>@Target</code> declaration is discouraged). |
337 |
To support both styles of annotations, JDT has published a major update of the annotation |
338 |
bundle <a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/package-summary.html"><code>org.eclipse.jdt.annotation</code></a>: |
339 |
Versions 1.1.x are old style declaration annotations; versions 2.0.0 and onward are type annotations. |
340 |
By increasing the major version an incompatibility is signaled. Users are advised to |
341 |
reference this library with an explicit version range, either <code>[1.1.0,2.0.0)</code> |
342 |
for declaration annotations or <code>[2.0.0,3.0.0)</code> for type annotations. |
343 |
</p> |
344 |
<p> |
345 |
The exact configuration depends of course on the flavor of project: |
346 |
<dl> |
347 |
<dt>Plain Java</dt> |
348 |
<dd>JDT continues to offer a quickfix for copying the annotation library into the |
349 |
project. The version will be determined by the compliance settings of the project.</dd> |
350 |
<dt>Maven</dt> |
351 |
<dd>Both versions of the annotation bundle will be published to <code>repo.eclipse.org</code>, |
352 |
from where they can be consumed using the regular maven mechanisms: be sure to specify |
353 |
the correct version; specifying <code><scope>compile</scope></code> is recommended |
354 |
for this dependency.</dd> |
355 |
<dt>OSGi / Eclipse</dt> |
356 |
<dd>When developing OSGi bundles / Eclipse plugins the version range should be specified as |
357 |
mentioned above. Unfortunately, OSGi doesn't support a concept of compile time dependencies. |
358 |
The PDE specific mechanism in file <code>build.properties</code> is problematic because |
359 |
it doesn't support specifying a version range. Thus the best approximation of the desired |
360 |
semantics is to use a <code>Require-Bundle</code> dependency. |
361 |
qualified with <code>resolution:=optional</code> in order to avoid forcing this dependency |
362 |
on the runtime.</dd> |
363 |
</dl> |
364 |
<h3 id="compatibility_semantics">Semantics</h3> |
365 |
<p> |
366 |
While the fundamental semantics of null annotation remains unchanged, |
367 |
the annotation <a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/NonNullByDefault.html" |
368 |
><code>@NonNullByDefault</code></a> has been changed slightly: |
369 |
<ul> |
370 |
<li>This annotation can now affect more locations.</li> |
371 |
<li>The locations to be affected can be fine tuned using the |
372 |
<a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/NonNullByDefault.html#value--" |
373 |
><code>value</code></a> property of the annotation |
374 |
(see also the enum <a href="/help/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/annotation/DefaultLocation.html" |
375 |
><code>DefaultLocation</code></a>).</li> |
376 |
<li>As a consequence, the notation for canceling a default from an outer scope has been changed, too: |
377 |
<table border="1" cellspacing="0" cellpadding="5" summary="Cancelling a default"> |
378 |
<tr><th>Declaration Annotations (Java 7 or below)</th><th>Type Annotation (Java 8)</th></tr> |
379 |
<tr><td><code>@NonNullByDefault(false)</code></td><td><code>@NonNullByDefault({})</code></td></tr> |
380 |
</table> |
381 |
</li> |
382 |
</ul> |
383 |
|
384 |
<h2 id="compiler_messages_explained">Compiler messages explained</h2> |
385 |
<p> |
386 |
In addition to <a href="/help/topic/org.eclipse.jdt.doc.user/tasks/task-using_null_annotations.htm#compiler_messages_explained">compiler messages of the previous version</a> the following |
387 |
messages may be issued, if null type annotations are enabled for analysis: |
388 |
<em>TODO</em> |
389 |
</p> |
390 |
|
391 |
</body> |
392 |
</html> |