Null-safe program in Java (Eclipse)

0. Introduction

I was wondering if it would be possible to check for nulls in Java every time, but I realized that Eclipse has a function called Null Analysis. (It seems that IntelliJ has implemented it first)

I've researched various things, so I will summarize how to use Null Analysys (as of October 2018). By the way, the Eclipse version I'm using is 2018-09 (4.9.0). Basically, Null Analysis can be done after Juno (4.2), but the latest version is better because there are various bugs.

1. What is Null Analysis?

A way to statically solve "I don't want to check null every time" by annotating it like Java. For more information, see Perform null analysis in Eclipse Juno.

Java 8 or later is required to properly benefit from Null Analysis. Without the JSR 308 type annotations implemented in Java 8, you wouldn't get much benefit.

2. Which annotation should be used

There are various annotations that are similar and different, such as those of Eclipse and those of IntelliJ IDEA, and it is difficult to select them.

In my case, I don't want to put the color of a specific IDE so much, so as an option, --JSR 305 `@ javax.annotation.Nonnull``` series --Checker Framework `@ org.checkerframework.checker.nullness.qual.NonNull``` system Will be either. For various annotations, What is Nonnull? is detailed.

Furthermore, considering the module system of Java 9 or later, JSR 305's `@ javax.annotation.Nonnull``` cannot be used. Simply put, if you try to use the external module ``` javax.annotation.Nonnull``` where` `javax.annotation. *` Is included as a Java standard module, the package namespace conflicts. To do it. See Making JSR 305 Work On Java 9 for details.

Therefore, the annotation to be used is an annotation of Checker Framework.

However, there is one problem with using it on Eclipse. In Eclipse, the target package for Null Analysis is judged by the @NonNullByDefault annotation, but since the Checker Framework treats all defaults as NonNull in the first place, it does not have an annotation like that (`@ DefaultQualifier`". Something is different .. Arguments are required).

Let's compromise a bit here and use Eclipse annotations for @ NonNullByDefault. If you switch later, you shouldn't have much trouble.

3. Preparation for Null Analysis

When using annotations, get it from Maven Central. `` `build.gradle``` An example is as follows.

// https://mvnrepository.com/artifact/org.checkerframework/checker-qual
implementation group: 'org.checkerframework', name: 'checker-qual', version: '2.5.6'
// https://mvnrepository.com/artifact/org.eclipse.jdt/org.eclipse.jdt.annotation
implementation group: 'org.eclipse.jdt', name: 'org.eclipse.jdt.annotation', version: '2.2.100'

Null Analysis is off by Eclipse standard, so compiler settings are also required. The method is What is Nonnull? It is written at the bottom.

4. How to write the code

4-1. Add `` `@ NonNullByDefault``` to your own package

Basically, all self-made packages are set to NonNull by default. Just annotate the package-info.java of your own package.

@org.eclipse.jdt.annotation.NonNullByDefault
package common.validator;

Then you will get the following code

public class Foo {
    String a;
    public String bar(String b) {
        String bb = b + b;
        return bb;
    }
}

As shown below, it looks like it has `` `@ NonNull``` as a whole.

public class Foo {
    @NonNull String a;  //The field is@NonNull

    @NonNull  //Return value@NonNull
    public String bar(@NonNull String b) { //Formal arguments@NonNull
        @NonNull String bb = bb + bb;  //Local variables too@NonNull
        return bb;
    }
}

4-2. `@ NonNull``` and `@ Nullable```

@nonnullIt is guaranteed at compile time (in real time when writing code in eclipse) that null is not entered in the place marked with. By the way, add @ Nullable to the place where you want to put null.

@nonnullIf you try to put null in a variable with, you will get a compile error and

@NonNull String a = null; //Compile error

If you try to assign a `@ Nullable``` variable to a `@ NonNull``` variable, even if it is not null, you will get a compile error.

@Nullable String a = "a";
@NonNull String s = a; //Compile error

The same applies to method calls. If you try to put a variable `` `@ Nullable``` in the method of the above example class, a compile error will occur.

Foo foo = new Foo();
@Nullable String nullableStr = "a";
String s = foo.bar(nullableStr); //Compile error here

Of course, it is possible to assign a variable that is `@ Nullable``` to a variable that is `@ NonNull```.

@NonNull String nonNullStr = "a";
@Nullable String nullableStr = nonNullStr; //OK

4-3. To make the @ Nullable variable @ NonNull

If you use the DTO pattern in communication with the outside, the value `@ Nullable``` will inevitably come in, so you need to convert it to @ NonNull``` by some means. External libraries do not add `` @ NonNull```, so the return value will be treated as `@ Nullable`.

The conversion is done by assigning to a variable that is @ NonNull, but if you assign it normally, a compilation error will occur, so tell the compiler that it is @ Nullable``` but it is not null. There is a need.

How to tell 1: Communicate with Objects in Java 7 introduction

objects#requirenonnull()If you pass it, the compiler will judge that it has been checked. This is easy to tell if it is obvious that null will not come. If null comesnullpointerexceptionbecome.

@Nullable String nullableStr = 〜〜;
Objects.requireNonNull(nullableStr); //NullPointerException when Null
@NonNull String nonNullStr = nullableStr; //OK

If you use Null Analysis, you will use this code frequently, so it is convenient to put it in the Java Editor Template. In my case, I have the following definitions. Write `reqn` and press `` `Ctrl + Space``` to get the code nicely.

Name                 : ReqNotNull
Context              : Java Statement
Automatically insert : true
Pattern:
${:import (java.util.Objects)}Objects.requireNonNull(${localVar})

How to convey 2: Communicate with an if statement

This way if you don't want to get a NullPointerException when it's null.

@Nullable String nullableStr = 〜〜;
if (nullableStr != null) { //Tell with an if statement
    @NonNull String nonNullStr = nullableStr; //OK
}

Other

If there is another way to tell, please let me know.

4-4. About container types like arrays / List

For arrays

A little consideration is required for arrays. If you declare a field normally (under the `@ NonNullByDefault``` package), the array variable itself becomes @ NonNull```, but the objects in the array are `` @ Nullable```. become.

public class Foo {
    String[] args;  //args is NonNull, but args[0]Is Nullable
}

If you want the contents to be `` `@ NonNull```, add annotations.

public class Foo {
    @NonNull String[] args;  //args also args[0]Also NonNull
}

The same is true when defining variadic arguments.

public class Foo {
    //No annotation
    public void bar(String...args) { 
        //args is NonNull, but args[0]Is Nullable
    }

    //With annotation
    public void baz(@NonNull String...args) {
        //args also args[0]Also NonNull
    }
}

For List

In the case of List, unlike an array, both the container and the contents are `` `@ NonNull```.

public class Foo {
    List<String> args;  //args also args.get(0)Also NonNull
}

5. Unclear points

A note of what I don't understand

--When using JSR 305 annotation, standard methods such as ```Object # toString () `` `were troublesome with Nullable, but with Checker Framework + Eclipse annotation, it was treated as NonNull. Why is it so?

--When using JSR 305 annotation, the default NonNull was only the formal argument of the method, but when using Checker Framework + Eclipse annotation, both the field and the return value were NonNull. Is Eclipse changing its behavior by looking at the annotation name?

6. Conclusion

I will add it when I have more knowledge.

Recommended Posts

Null-safe program in Java (Eclipse)
First Java development in Eclipse
Get Null-safe Map values in Java
Try running Selenuim 3.141.59 in eclipse (java)
Hello World in java in eclipse now
Create a Servlet program in Eclipse
JPA (Java Persistence API) in Eclipse
Changes in Java 11
Rock-paper-scissors in Java
MVC in Eclipse.
[Java] Set AdoptOpen JDK in STS (Eclipse)
Play Framework 2.6 (Java) environment construction in Eclipse
Program PDF headers and footers in Java
Pi in Java
FizzBuzz in Java
I made a primality test program in Java
[Java] API creation using Jerjey (Jax-rs) in eclipse
I wrote a primality test program in Java
I wrote a prime factorization program in Java
[java] sort in list
Read JSON in Java
Make Blackjack in Java
Constraint programming in Java
Put java8 in centos7
Java (eclipse) installation procedure
Eclipse ~ Java project creation ~
NVL-ish guy in Java
Combine arrays in Java
"Hello World" in Java
Callable Interface in Java
Comments in Java source
Azure functions in java
Format XML in Java
Simple htmlspecialchars in Java
To debug in eclipse
Hello World in Java
Use OpenCV in Java
webApi memorandum in java
Type determination in Java
Ping commands in Java
Various threads in java
Heapsort implementation (in java)
Zabbix API in Java
ASCII art in Java
Compare Lists in Java
POST JSON in Java
Express failure in Java
Create JSON in Java
Date manipulation in Java 8
What's new in Java 8
Use PreparedStatement in Java
What's new in Java 9,10,11
Parallel execution in Java
Initializing HashMap in Java
[Java] Calculator program creation 1
[LeJOS] Let's program mindstorm-EV3 in Java [Environment construction part 2]
How to Git manage Java EE projects in Eclipse
Call a program written in Swift from Processing (Java)
Try using RocksDB in Java
Avoid Yubaba's error in Java
Get EXIF information in Java