PUBLIC OBJECT

Inside Guice 2: injecting null

Part 2 in a Series.

Background: marking nulls

Null is bad. Most of the time, use of null indicates clumsy modeling. Instead of null collections, use empty ones. Instead of a null service, use a no-op implementation. The JDK gets this wrong for comparators by using null as a stand-in for natural order; the result is special cases instead of polymorphism.

To help you to detect null problems sooner, Guice refuses to inject null by default. When asked to do so, it will fail with a ProvisionException instead. This increases your confidence in your app by eliminating an entire category of runtime problems.

But sometimes — and only sometimes — null is necessary. Value objects don't lend themselves to the null object pattern. And in some cases you can be sure that a null reference won't be used. To make intentional null use explicit, you can use one of several @Nullable annotations, including those from FindBugs, IntelliJ or old snapshots of Google Collections. These will soon be standardized by another @Nullable in JSR 305.

Injecting null

Guice tolerates null to be injected wherever a parameter is annotated @Nullable:

  public Person(String firstName, String lastName, @Nullable Phone phone) {
    this.firstName = checkNotNull(firstName, "firstName");
    this.lastName = checkNotNull(lastName, "lastName");
    this.phone = phone;
  }`</pre>
But which `@Nullable`?

Rather than arbitrarily choosing an `@Nullable` to support (and alienating everyone else), Guice permits any `Nullable` annotation to be used. And I do mean _any_: it scans the injected parameter or field's annotations, looking at their names. If any has the simple name `Nullable`, it is honoured. This means that  even your company's internal `com.company.util.Nullable` will work.

### More generally

This trick works particularly nicely for annotations, since they tag objects without adding behaviour. It also avoids an aggravating problem, where code that _looks_ right doesn't _work_ right. Consider:
<pre class="prettyprint">`import com.google.inject.Inject;
import javax.annotation.Named;

public class RealPaymentService implements PaymentService {

  @Inject
  public RealPaymentService(@Named("creditcard") Processor processor) {
    ...
  }
}

This code appears legitimate, and it might even execute without error. But the wrong @Named annotation is applied! The unreleased javax.annotation.Named is incompatible with Guice and has no effect. Since it looks the same as com.google.inject.name.Named, there's potential for error.

When applying annotations, be careful about overlapping names. When processing them, be mindful of mistakes! What's the annotation-equivalent of a precondition? If a user applies an annotation incorrectly, is it detected?

Part 3.