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.
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.
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.
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.
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;
}
}
`@ NonNull``` and
`@ Nullable```@nonnull
It 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.
@nonnull
If 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
@ 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.
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 comesnullpointerexception
become.
@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})
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
}
If there is another way to tell, please let me know.
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
}
}
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
}
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?
I will add it when I have more knowledge.
Recommended Posts