or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

default-annotations.mdindex.mdnull-safety.mdresource-management.mdreturn-value-checking.mdtesting-annotations.mdwarning-suppression.md

null-safety.mddocs/

0

# Null Safety

1

2

Comprehensive null safety annotation system for expressing nullability constraints and enabling safer code through static analysis. These annotations integrate with SpotBugs and other tools to detect null pointer exceptions at compile time.

3

4

## Capabilities

5

6

### NonNull Annotation

7

8

Indicates that the annotated element must not be null.

9

10

```java { .api }

11

/**

12

* The annotated element must not be null.

13

*

14

* Annotated Fields must only not be null after construction has completed.

15

* Annotated methods must have non-null return values.

16

*/

17

@Documented

18

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

19

@Retention(RetentionPolicy.CLASS)

20

@javax.annotation.Nonnull(when = When.ALWAYS)

21

@TypeQualifierNickname

22

@interface NonNull {

23

}

24

```

25

26

**Usage Examples:**

27

28

```java

29

public class UserService {

30

// Non-null field - must be initialized

31

@NonNull

32

private final UserRepository repository;

33

34

public UserService(@NonNull UserRepository repository) {

35

this.repository = repository; // Required - cannot be null

36

}

37

38

// Non-null return value

39

@NonNull

40

public String getUserName(@NonNull String userId) {

41

// Must return non-null value

42

String name = repository.findNameById(userId);

43

return name != null ? name : "Unknown";

44

}

45

46

// Non-null parameter

47

public void updateUser(@NonNull User user) {

48

// Can safely use user without null check

49

repository.save(user);

50

}

51

}

52

```

53

54

### Nullable Annotation

55

56

Indicates that the annotated element could be null under some circumstances.

57

58

```java { .api }

59

/**

60

* The annotated element could be null under some circumstances.

61

*

62

* In general, this means developers will have to read the documentation to

63

* determine when a null value is acceptable and whether it is necessary to

64

* check for a null value.

65

*

66

* When this annotation is applied to a method it applies to the method return value.

67

*/

68

@Documented

69

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

70

@Retention(RetentionPolicy.CLASS)

71

@javax.annotation.Nonnull(when = When.UNKNOWN)

72

@TypeQualifierNickname

73

@interface Nullable {

74

}

75

```

76

77

**Usage Examples:**

78

79

```java

80

public class UserService {

81

// Nullable field - may be null

82

@Nullable

83

private String cachedData;

84

85

// Nullable return value - may return null

86

@Nullable

87

public User findUser(@NonNull String userId) {

88

return repository.findById(userId); // May return null if not found

89

}

90

91

// Nullable parameter - null is acceptable

92

public void setDisplayName(@Nullable String displayName) {

93

// Must check for null before use

94

this.displayName = displayName != null ? displayName : "Anonymous";

95

}

96

97

// Handle nullable values safely

98

public void processUser(@NonNull String userId) {

99

@Nullable User user = findUser(userId);

100

if (user != null) {

101

// Safe to use user here

102

user.updateLastAccess();

103

}

104

}

105

}

106

```

107

108

### CheckForNull Annotation

109

110

Indicates that the annotated element might be null and uses of the element should check for null.

111

112

```java { .api }

113

/**

114

* The annotated element might be null, and uses of the element should check for

115

* null.

116

*

117

* When this annotation is applied to a method it applies to the method return value.

118

*/

119

@Documented

120

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

121

@Retention(RetentionPolicy.CLASS)

122

@javax.annotation.Nonnull(when = When.MAYBE)

123

@TypeQualifierNickname

124

@interface CheckForNull {

125

}

126

```

127

128

**Usage Examples:**

129

130

```java

131

public class CacheService {

132

// Check for null before using

133

@CheckForNull

134

public String getCachedValue(@NonNull String key) {

135

String value = cache.get(key);

136

return value; // Explicitly check for null before using result

137

}

138

139

public void processData(@NonNull String key) {

140

@CheckForNull String data = getCachedValue(key);

141

142

// Must check for null - static analysis will warn if you don't

143

if (data != null) {

144

System.out.println(data.length());

145

} else {

146

System.out.println("No cached data found");

147

}

148

}

149

}

150

```

151

152

### UnknownNullness Annotation

153

154

Indicates that the nullness of the annotated element is unknown, or may vary in unknown ways in subclasses.

155

156

```java { .api }

157

/**

158

* Used to indicate that the nullness of element is unknown, or may vary in

159

* unknown ways in subclasses.

160

*/

161

@Documented

162

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

163

@Retention(RetentionPolicy.CLASS)

164

@javax.annotation.Nonnull(when = When.UNKNOWN)

165

@TypeQualifierNickname

166

@interface UnknownNullness {

167

}

168

```

169

170

**Usage Examples:**

171

172

```java

173

public class LegacyIntegration {

174

// Nullness unknown - treat with caution

175

@UnknownNullness

176

public Object callLegacyApi(@NonNull String request) {

177

// Legacy API with unclear null handling

178

return legacySystem.process(request);

179

}

180

181

public void handleLegacyResult(@NonNull String request) {

182

@UnknownNullness Object result = callLegacyApi(request);

183

184

// Defensive programming - assume it might be null

185

if (result != null) {

186

processResult(result);

187

}

188

}

189

}

190

```

191

192

### PossiblyNull Annotation (Deprecated)

193

194

Indicates that the annotated element might be null, and uses of the element should check for null.

195

196

```java { .api }

197

/**

198

* The annotated element should might be null, and uses of the element should

199

* check for null.

200

*

201

* When this annotation is applied to a method it applies to the method return

202

* value.

203

*

204

* @deprecated - use CheckForNull instead; the name of which more clearly

205

* indicates that not only could the value be null, but that good

206

* coding practice requires that the value be checked for null.

207

*/

208

@Documented

209

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

210

@Retention(RetentionPolicy.CLASS)

211

@javax.annotation.Nonnull(when = When.MAYBE)

212

@TypeQualifierNickname

213

@Deprecated

214

@interface PossiblyNull {

215

}

216

```

217

218

**Usage Examples (Deprecated - Use @CheckForNull instead):**

219

220

```java

221

public class LegacyService {

222

// Legacy usage - prefer @CheckForNull

223

@PossiblyNull

224

@Deprecated

225

private final Logger logger;

226

227

public LegacyService(boolean enableLogging) {

228

this.logger = enableLogging ? LoggerFactory.getLogger(getClass()) : null;

229

}

230

231

// Better approach using @CheckForNull:

232

@CheckForNull

233

public String getDebugInfo() {

234

return logger != null ? logger.getName() : null;

235

}

236

237

public void logMessage(@NonNull String message) {

238

// Handle possibly null logger

239

if (logger != null) {

240

logger.info(message);

241

}

242

}

243

}

244

```

245

246

### ReturnValuesAreNonnullByDefault Annotation

247

248

Indicates that methods in the annotated scope have nonnull return values by default.

249

250

```java { .api }

251

/**

252

* This annotation can be applied to a package, class or method to indicate that

253

* the methods in that element have nonnull return values by default unless

254

* there is:

255

* <ul>

256

* <li>An explicit nullness annotation

257

* <li>The method overrides a method in a superclass (in which case the

258

* annotation of the corresponding parameter in the superclass applies)

259

* <li>there is a default annotation applied to a more tightly nested element.

260

* </ul>

261

*/

262

@Documented

263

@Nonnull

264

@TypeQualifierDefault(ElementType.METHOD)

265

@Retention(RetentionPolicy.RUNTIME)

266

@interface ReturnValuesAreNonnullByDefault {

267

}

268

```

269

270

**Usage Examples:**

271

272

```java

273

// Applied to class - all methods return non-null by default

274

@ReturnValuesAreNonnullByDefault

275

public class UserService {

276

277

// Returns non-null by default

278

public String getUserName(String userId) {

279

String name = repository.findNameById(userId);

280

return name != null ? name : "Unknown"; // Must ensure non-null return

281

}

282

283

// Explicit annotation overrides default

284

@Nullable

285

public User findUser(String userId) {

286

return repository.findById(userId); // May return null

287

}

288

289

// Still non-null by default

290

public List<User> getAllUsers() {

291

List<User> users = repository.findAll();

292

return users != null ? users : Collections.emptyList();

293

}

294

}

295

296

// Can also be applied to packages in package-info.java:

297

@ReturnValuesAreNonnullByDefault

298

package com.example.service;

299

```

300

301

## Null Safety Best Practices

302

303

1. **Use @NonNull by default**: Start with the assumption that references should not be null

304

2. **Explicit @Nullable**: Only use @Nullable when null is a valid, expected value

305

3. **Check before use**: Always check @Nullable and @CheckForNull values before dereferencing

306

4. **Document null handling**: Use clear parameter and return value documentation

307

5. **Consistent application**: Apply annotations consistently across your codebase

308

6. **Default annotations**: Use @ReturnValuesAreNonnullByDefault to reduce annotation overhead

309

310

## Integration with Other Tools

311

312

These annotations work with:

313

- **SpotBugs**: Primary static analysis integration

314

- **NullAway**: Uber's null safety checker

315

- **Checker Framework**: Advanced static analysis

316

- **IDEs**: IntelliJ IDEA, Eclipse null analysis

317

- **Error Prone**: Google's static analysis tool