2

I am not clear about how we properly use the annotation about nullable i.e. NonNull and Nullable.
I am not really comfortable with something like the following:

public void foo(@NonNull ArrayList<CustomObject> list) {  
   CustomObject o = list.get(0);  //etc
}  

1) Is it non-sense to declare non-null and code defensively?
2) What is the most effective way to use such annotations? E.g. as an example
- how should they be used when using the builder pattern or
- when defining an interface for concrete classes to implement? Should the method of implementing classes also contain the annotation or is it assumed?
3) In the snippet above is there a way to define non-null and non-empty?

Jim
  • 18,826
  • 34
  • 135
  • 254
  • I usually use `@NonNull` when I know a variable is guaranteed not to be null. As far as I'm aware it makes no difference to the compiled code, but suppresses all "might be `null`" warnings in the IDE. Conversely I use `@Nullable` where there are occasions where I *want* a variable to be null. – Michael Dodd Feb 24 '17 at 21:14
  • @MichaelDodd:Isn't that for your own self-documenting purposes when reviewing your code? What about a method that *other* devs will use/access e.g. a utility method or a method meant to be part of a module or library? – Jim Feb 24 '17 at 21:57
  • I suppose documentation and readability is the whole purpose of `android-annotations`. In my team at work we extensively use those annotations to clarify that a variable may/should never be `null`. Likewise, if library method a is annotated as such, it becomes advice as to whether or not a `null` check is required. – Michael Dodd Feb 24 '17 at 22:08
  • @MichaelDodd: Yes and what is the expected behavior? Declare a variable that should never be null and then access it without checking for null? Or check for null and throw an explicit NPE? Or check for null and stop processing and return some error value? – Jim Feb 25 '17 at 09:59
  • 1
    It all depends on your enviornment. In fact, [Kotlin's support of `@NonNull`](https://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations) allows occurnaces of compile time errors when attempting to use `null`. In some enviornments, `@NonNull` could be teaching the defensive coding styles. – Vince Feb 26 '17 at 05:33
  • See https://stackoverflow.com/questions/4963300 – tkruse Jul 28 '18 at 01:16

1 Answers1

0

Now I've had proper time to investigate, this is what I've found.

1)

It makes perfect sense to still code defensively while using the @NonNull annotation. Just because a parameter has a @NonNull annotation, null can still be passed at runtime. For example, with a data class like:

class DataClass {
    @NonNull private String notNullString;

    public DataClass() { notNullString = null; }

    public String toString() { return notNullString; }
}

The IDE will warn that you're assigning null to a @NonNull variable, but calling toString() will return null. To get around this, and IDE warnings asking why you're null-checking a @NonNull variable, Google tends to use PreConditions.checkNotNull(T) - see example code.

2)

As mentioned in the comments, personally I use the annotations as guidance as to whether null is an expected value or not. I can't find any solid examples of this being used within a builder pattern, but potentially you can enforce this by using checkNotNull() in your build() method so that any unexpected null values throw a NullPointerException.

As for the concrete class, it's up to you but personally I would add them for consistency.

3)

Given the above, I'd do it this way:

public void foo(@NonNull ArrayList<CustomObject> list) {
    checkNotNull(list, "List is null!");
    if (!list.isEmpty()) {  
        CustomObject o = list.get(0);  //etc
    }
}  
Community
  • 1
  • 1
Michael Dodd
  • 10,102
  • 12
  • 51
  • 64
  • In my mind I was expecting that the purpose of the annotation would be to promote a design by contract there by reducing the myriads of check for null leading to slightly more optimized (less ifs) and cleaner code. If we are expected to check for null anyway then it seems that the reasoning is too complex. I understand that it helps in documenting things but it all depends in the end how one thinks of what @NonNull. Do I make sense? – Jim Feb 25 '17 at 12:36
  • Yeah that makes sense. In an ideal world there should be an accompanying `annotationProcessor` that ensures that anything marked `@NonNull` is never assigned `null`. However, it would also need to check that the same variable is always assigned with a default value, else [uninitialized objects](http://stackoverflow.com/questions/16699593/uninitialized-object-vs-object-initialized-to-null) will become a problem. That would introduce a new set of problems. – Michael Dodd Feb 25 '17 at 12:54