View | Details | Raw Unified | Return to bug 431566
Collapse All | Expand All

(-)a/bundles/org.eclipse.jdt.doc.user/tasks/task-using_null_annotations.htm (-30 / +15 lines)
Lines 88-94 Link Here
88
<li>Method return (syntactically a method annotation is used here)</li>
88
<li>Method return (syntactically a method annotation is used here)</li>
89
<li>Local variables</li>
89
<li>Local variables</li>
90
<li>Fields</li>
90
<li>Fields</li>
91
<li><em>(more to come in the future)</em></li>
91
<li>In Java 8, more locations can be annotated with <a href="task-using_null_annotations.htm">null type annotations</a></li>
92
</ul>
92
</ul>
93
<p><code>@NonNullByDefault</code> is supported for</p>
93
<p><code>@NonNullByDefault</code> is supported for</p>
94
<ul>
94
<ul>
Lines 100-105 Link Here
100
Note, that even the actual qualified names of these annotations are 
100
Note, that even the actual qualified names of these annotations are 
101
<a href="../reference/preferences/java/compiler/ref-preferences-errors-warnings.htm#null_annotation_names">configurable</a>,
101
<a href="../reference/preferences/java/compiler/ref-preferences-errors-warnings.htm#null_annotation_names">configurable</a>,
102
but by default the ones given above are used (from the package <code>org.eclipse.jdt.annotation</code>).
102
but by default the ones given above are used (from the package <code>org.eclipse.jdt.annotation</code>).
103
When using 3rd party null annotations, please ensure that those are properly defined using at least a <code>@Target</code>
104
meta annotation, because otherwise the compiler can not distinguish between declaration annotations (Java 5)
105
and type annotations (Java 8). 
103
</p>
106
</p>
104
107
105
<h2 id="buildpath_setup">Setup of the build path</h2>
108
<h2 id="buildpath_setup">Setup of the build path</h2>
Lines 363-401 Link Here
363
</p>
366
</p>
364
<h2 id="complete_specification">Complete specification using an extended type system</h2>
367
<h2 id="complete_specification">Complete specification using an extended type system</h2>
365
<p>
368
<p>
366
The support for null annotations has been designed in a way that is compatible to
369
The support for null annotations had been designed in a way that should be compatible to
367
a future extension, whereby the compiler will be able to guarantee that a certified
370
a future extension. 
368
program will never throw a NullPointerException at runtime (with the typical caveats
371
This extension has become part of the Java language as <strong>type annotations (JSR 308)</strong>,
369
about uncheckable parts like reflection).
372
which have been introduced in Java 8.
370
While no promise can be made yet regarding such future extension, the basic idea
373
JDT supports to leverage the new concept for 
371
is just a different interpretation of what we already have. 
374
<a href="task-using_null_type_annotations.htm">null type annotations</a>.
372
</p>
373
<p>
374
By interpreting null annotations as part of the type system we double the number
375
of types in a given program: for any given class <code>Cn</code>, the class itself
376
is no longer considered as a legal type, but only "<code>@NonNull Cn</code>" and
377
"<code>@Nullable Cn</code>" are useful types. So ideally for every value in a program
378
we will know if it can be null (and must be checked before dereference) or not.
379
If we exclude the third option (un-annotated types) then the compiler can rigorously
380
flag <em>every</em> unsafe usage.
381
</p>
382
<p>
383
The current implementation has a major limitation with regard to this goal:
384
<ul>
385
<li>The Java syntax doesn't allow annotations in some relevant locations,
386
	a limitation that is addressed by JSR-308 (scheduled for Java 8).</li>
387
</ul>
388
<p>
389
As of today and despite the current limitation, the vision of fully specified and
390
completely checked programs has already some implications that shaped the current
391
analysis and the errors/warnings reported by the compiler.
392
The details will be presented by explaining the rules that the compiler checks
393
and the messages it issues upon violation of a rule.
394
</p>
375
</p>
395
<h2 id="compiler_messages_explained">Compiler messages explained</h2>
376
<h2 id="compiler_messages_explained">Compiler messages explained</h2>
396
<p>
377
<p>
378
Semantic details of annotation based null analysis are presented here, by explaining the rules
379
that the compiler checks and the messages it issues upon violation of a rule.
380
</p>
381
<p>
397
On the corresponding <a href="../reference/preferences/java/compiler/ref-preferences-errors-warnings.htm">preference page</a>
382
On the corresponding <a href="../reference/preferences/java/compiler/ref-preferences-errors-warnings.htm">preference page</a>
398
the individual rules checked by the compiler are ground under the following headings: 
383
the individual rules checked by the compiler are grouped under the following headings: 
399
</p>
384
</p>
400
<h3>Violation of null specification</h3>
385
<h3>Violation of null specification</h3>
401
<p>As specification violation we handle any situation where a null annotation
386
<p>As specification violation we handle any situation where a null annotation
(-)a/bundles/org.eclipse.jdt.doc.user/tasks/task-using_null_type_annotations.htm (+392 lines)
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&lt;T0 extends @Nullable Object&gt; {} // meaningless, no constraint imposed
95
    class C1&lt;T1 extends @NonNull Object&gt; {}
96
    ...
97
    // usage:
98
    C1&lt;@NonNull String&gt; c1String;  // legal
99
    C1&lt;@Nullable String&gt; 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&lt;@Nullable T2&gt; {}
108
    ...
109
    // usage:
110
    C2&lt;@NonNull String&gt; c2String;  // illegal
111
    C2&lt;@Nullable String&gt; 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&lt;T1 extends @NonNull Number&gt; {
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&lt;@Nullable T2 extends Number&gt; {
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&lt;T extends Number&gt; {
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&lt;<strong>@NonNull Integer</strong>&gt; 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&lt;<strong>@Nullable Integer</strong>&gt; 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>    &lt;T&gt; T check(T in) { return in; }
222
    void test(@NonNull List&lt;@Nullable String&gt; someStrings) {
223
        @NonNull List&lt;@Nullable String&gt; 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>&lt;T&gt;</code>
230
to <code>@NonNull List&lt;@Nullable String&gt;</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 &lt;T&gt; 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>&lt;scope&gt;compile&lt;/scope&gt;</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>
(-)a/bundles/org.eclipse.jdt.doc.user/topics_Tasks.xml (+14 lines)
Lines 126-131 Link Here
126
			<topic href="tasks/task-using_null_annotations.htm#compiler_messages_explained" label="Compiler messages explained"></topic>
126
			<topic href="tasks/task-using_null_annotations.htm#compiler_messages_explained" label="Compiler messages explained"></topic>
127
			<topic href="tasks/task-using_null_annotations.htm#tips_analyzable" label="Tips for making code better analyzable"></topic>
127
			<topic href="tasks/task-using_null_annotations.htm#tips_analyzable" label="Tips for making code better analyzable"></topic>
128
			<topic href="tasks/task-using_null_annotations.htm#tips_adoption" label="Tips for adopting null annotations"></topic>
128
			<topic href="tasks/task-using_null_annotations.htm#tips_adoption" label="Tips for adopting null annotations"></topic>
129
			<topic href="tasks/task-using_null_type_annotations.htm" label="Using null type annotations">
130
				<topic href="tasks/task-using_null_type_annotations.htm#generics" label="Generics">
131
					<topic href="tasks/task-using_null_type_annotations.htm#typeParameters" label="Type parameters"></topic>
132
					<topic href="tasks/task-using_null_type_annotations.htm#typeVariables" label="Type variables"></topic>
133
					<topic href="tasks/task-using_null_type_annotations.htm#typeArguments" label="Type arguments"></topic>
134
				</topic>
135
				<topic href="tasks/task-using_null_type_annotations.htm#inference" label="Inference"></topic>
136
				<topic href="tasks/task-using_null_type_annotations.htm#more_locations" label="More locations"></topic>
137
				<topic href="tasks/task-using_null_type_annotations.htm#compatibility" label="Compatibility">
138
					<topic href="tasks/task-using_null_type_annotations.htm#compatibility_syntax" label="Syntax"></topic>
139
					<topic href="tasks/task-using_null_type_annotations.htm#compatibility_configuration" label="Project configuration"></topic>
140
					<topic href="tasks/task-using_null_type_annotations.htm#compatibility_semantics" label="Semantics"></topic>
141
				</topic>
142
			</topic>
129
		</topic>
143
		</topic>
130
		<topic href="tasks/task-avoiding_resource_leaks.htm" label="Avoiding resource leaks"></topic>
144
		<topic href="tasks/task-avoiding_resource_leaks.htm" label="Avoiding resource leaks"></topic>
131
		<topic href="tasks/task-ensuring_switch_completeness.htm" label="Ensuring completeness of switch statements"></topic>
145
		<topic href="tasks/task-ensuring_switch_completeness.htm" label="Ensuring completeness of switch statements"></topic>

Return to bug 431566