liveBook · Manning

Defensive check

As explained in 100 Java Mistakes and How to Avoid Them

A defensive check is an input validation performed at a boundary to reject invalid values before they can corrupt program state.

A defensive check validates a value at an API boundary before the value reaches fields or later logic. In Java, this commonly means rejecting null inputs and out-of-range indexes at public methods or constructors, so a bad call fails near its cause rather than producing a later NullPointerException or corrupted state. section 5.5 section 5.1.1

Use a check when null is not part of the contract. Objects.requireNonNull() makes that contract explicit and prevents an object from being created with a required field missing. Collections deserve the same consideration: accepting a collection while silently retaining null elements moves the failure to an unrelated iteration or lookup later. section 5.1.1 section 5.1.1

public class Person {
  private final String firstName, lastName;

  public Person(String firstName, String lastName) {
    this.firstName = Objects.requireNonNull(firstName);
    this.lastName = Objects.requireNonNull(lastName);
  }
}

A constructor checks required names before assigning them to final fields, making invalid Person instances impossible through this constructor. section 5.1.1

public void process(Collection<String> data) {
  data.forEach(Objects::requireNonNull);
  …
}

Checking every collection element establishes a non-null element contract before subsequent processing begins. section 5.1.1

Keep defensive checks focused on values the boundary promises to accept:

  • Check required arguments immediately, especially before saving them to fields. section 5.5
  • Check indexes against the expected range before using or storing them. section 5.5
  • Validate that input collections contain no nulls when later processing requires non-null elements; account for the possible performance cost. section 5.1.1
  • Prefer an exception with detailed error information when an error cannot be recovered from, rather than returning null. section 5.1.1

A defensive check is not a reason to use null as an error signal elsewhere. Returning null for Collection, Stream, Optional, arrays, maps, or collection elements leaves callers to discover an undocumented exceptional state. Return an empty container when that represents the result; where a third state is meaningful, make it explicit with an enum rather than a boxed Boolean that can be null. section 5.1.1 section 5.1.1

Make a three-way answer explicit

A confirmation action with Yes, No, and Cancel cannot be represented safely by a boolean without losing or hiding one outcome. An enum such as YES, NO, CANCEL lets a switch handle each result directly, avoiding null unboxing and making cancellation visible in the control flow. section 5.1.1

Static analysis can reinforce a non-null API contract but does not replace boundary checks. IntelliJ IDEA, SonarLint, and SpotBugs can report explicit null returns where Optional, collections, or arrays are expected; warnings still need review against the intended contract. section 5.1.1

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains boundary checks through requireNonNull, collection-element validation, and prevention rules, without detailing implementation internals.
Examples
Uses constructor-required names, collection element checks, null-returning containers, and three-way confirmation answers.
What it assumes
Assumes Java familiarity with public methods, fields, collections, and null while teaching boundary-validation practice directly.
What you can do after
Apply it via Objects.requireNonNull and related checks to fail early on invalid API inputs.
How it connects
Connects null handling with NullPointerException, Optional, collections, enums, boxed primitives, and static analysis.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.