The solution to your problem
Problem location:
In the first line of the stack exception message, you can find the location of the null pointer. If this is not the class you wrote, you can scroll down to find the class you wrote, which is the empty pointer that appears here.
Solve the problem:
When a method or property in an empty object is called, it will report an empty pointer and check why the object is empty.
Several solutions to Java null pointer exception
Any object in Java may be empty. When we call the method of an empty object, we will throw a NullPointerException, which is a very common error type. We can use several methods to avoid this exception and make our code more robust. This paper will list these solutions, including traditional null detection, programming specifications and various tools introduced by modern Java language as assistance.
Runtime detection
The most obvious method is to use if (obj == null) to detect all objects that need to be used, including function parameters, return values and member variables of class instances. When a null value is detected, you can choose to throw a more targeted exception type, such as IllegalArgumentException, and add the message content. We can use some library functions to simplify the code, such as the Objects#requireNonNull method provided by Java 7 at first:
public void testObjects(Object arg){
Objectchecked = objects. Require nonnull (arg, "arg cannot be null");
checked . tostring(); }
Guava's prerequisite class also provides a series of tool functions to detect the legality of parameters, including null value detection:
public void test guava(Object arg){
Objectchecked = preceditions. checknot null (arg, "%s cannot be null", "arg");
checked . tostring();
}
We can also use Lombok to generate null detection code, throw a null pointer exception and give a prompt:
public void test lombok(@ NonNull Object arg){
arg . tostring();
The generated code is as follows:
public void testlombokkgenerated(Object arg){
if (arg == null) {
Throw a new NullPointerException("arg is marked as @NonNull, but it is null ");
}
arg . tostring();
}
This annotation can also be used on member variables of class instances, and all assignment operations will automatically detect null values.
Programming specification
By following some programming specifications, the occurrence of null pointer exceptions can also be reduced to some extent.
Use methods that have judged null values, such as String#equals, String#valueOf and functions used in tripartite libraries to judge whether strings and collections are empty:
if (str! = null & amp& ampstr . equals(" text "){ }
If ("text". equals(str)) {}
if (obj! = null){ obj . tostring(); }
string . value of(obj); //"empty"
//From the spring core
string utils . isempty(str);
collection utils . isempty(col);
//From Guava
strings . isnullorempty(str);
//from commons-collections4
collection utils . isempty(col);
If the parameter of one function can receive null value, consider rewriting it into two functions and using different function signatures, so that each parameter can be forced to be not empty:
public void method a(Object arg 1){
MethodB(arg 1, new object [0]);
}
public void method b(Object arg 1,Object[] arg2) {
For (Object obj: arg2) {} // No empty check.
}
If the return value of the function is set type, when the result is empty, an empty set is returned instead of a null value; If the return value type is an object, you can choose to throw an exception. This is how Spring JdbcTemplate is handled:
//When the query result is empty, a new ArrayList is returned.
JDBC template . query forlist(" SELECT * FROM person ");
//If the record cannot be found, an EmptyResultDataAccessException will be thrown.
JDBC template . query for object(" SELECT age FROM person WHERE id = 1 ",integer . class);
//Support generic collections
Public & ltT> list & ltT & gttestReturnCollection() {
Returns collections. emptylist ();
}
Static code analysis
There are many static code analysis tools in Java language, such as Eclipse IDE, SpotBugs, Checker Framework, etc. It can help programmers detect compile-time errors. Combined with annotations such as @Nullable and @Nonnull, we can find the code that may throw a null pointer exception before the program runs.
However, the annotation of zero detection has not been standardized. Although the community put forward the JSR 305 specification in September 2006, it has been put on hold for a long time. Many third-party libraries provide similar annotations and are supported by different tools, including:
Javax.annotation.Nonnull: proposed by JSR 305, and the reference implementation is com.google.code.findbugs.jsr305;
Org。 Eclipse. JDT. Annotation. Nonnull: Null detection annotation natively supported by Eclipse IDE;
Edu.umd.cs.findbugs.annotations.nonnull: Annotations used by Spotbugs, based on findbugs.jsr305;;
Org.springframework.lang.nonnull: Spring Framework 5.0 is available;
Org.checker framework.checker.nullness.qual.nonnull: Checker framework uses;
Android.support.annotation.nonnull: integrated in Android development tools;
I suggest using a cross-IDE solution, such as SpotBugs or Checker Framework, which can be well combined with Maven.
SpotBugs and @NonNull, @CheckForNull
SpotBugs is the successor of FindBugs. SpotBugs can help us detect null values at compile time by adding @NonNull and @CheckForNull annotations to the parameters and return values of methods. It should be noted that SpotBugs does not support the annotation @Nullable and must be replaced with @CheckForNull. As stated in the official document, @Nullable is only used when you need to override @ParametersAreNonnullByDefault.
The official documentation explains how to apply SpotBugs to Maven and Eclipse. We also need to add spotbugs-annotations to the project dependencies to use the corresponding annotations.
& lt dependency & gt
& ltgroupId & gtcom . github . spot bugs & lt; /groupId & gt;
& ltartifactid > spotbugs-comments ;
& lt version & gt3.1.7 < /version & gt;
& lt/dependency & gt;
The following are descriptions of different usage scenarios:
@NonNull
Private object returnNonNull() {
//Error: returnNonNull () may return Null, but it has been declared as @Nonnull.
Returns null
}
@CheckForNull
Private object returnNullable() {
Returns null
}
public void testReturnNullable(){
object obj = return nullable();
//Error: The return value of the method may be empty.
system . out . println(obj . tostring());
}
Private void argument nonnull (@ nonnull objectarg) {
system . out . println(arg . tostring());
}
public void testArgumentNonNull(){
//Error: Cannot pass null to a non-empty parameter.
argumentNonNull(null);
}
public void testNullableArgument(@ CheckForNull Object arg){
//Error: The parameter may be empty.
system . out . println(arg . tostring());
}
For Eclipse users, you can also use the IDE's built-in null detection tool by replacing the default annotation org. Eclipse.jdt.annotation.nullable with SpotBugs annotation:
Checker framework and @NonNull, @Nullable
Checker Framework can run as a plug-in of javac compiler, which can detect data types in code and prevent various problems. We can refer to the official documents, combine the Checker framework with maven-compiler-plugin, and then check every time mvn compile is executed. Checker Framework's empty detector supports almost all annotations, including JSR 305, Eclipse and even lombok.NonNull.
Import org.checker framework.checker.nullity.qual.nullable;
@Nullable
Private object returnNullable() {
Returns null
}
public void testReturnNullable(){
object obj = return nullable();
//Error: obj may be empty.
system . out . println(obj . tostring());
}
By default, Checker Framework applies @NonNull to all function parameters and return values. Therefore, even if this comment is not added, the following programs will not compile:
Private object returnNonNull() {
//Error: The method was declared as @NonNull, but returned Null.
Returns null
}
Private void argument nonnull (objectarg) (
system . out . println(arg . tostring());
}
public void testArgumentNonNull(){
//Error: The parameter was declared as @NonNull, but Null was passed in.
argumentNonNull(null);
}
Checker Framework is very useful for users who use Spring Framework 5.0 or above, because Spring provides built-in empty detection comments and can be supported by Checker Framework. On the one hand, we don't need to introduce additional Jar packages. More importantly, the Spring framework code itself uses these comments, so that we can effectively handle null values when calling its API. For example, functions that can pass in null values and functions that return null values in the StringUtils class have added @Nullable comments, while methods that have not been added inherit the @NonNull comments of the whole framework. Therefore, the Checker framework can detect null pointer exceptions in the following code:
//This is the class and method defined in spring-core.
Public abstract class StringUtils {
The str parameter inherits the global @NonNull annotation.
Public static string capitalization (String str) {}
@Nullable
Public static string getFilename(@ nullable string path) {}
}
//Error: The parameter was declared as @NonNull, but Null was passed in.
string utils . capital(null);
string filename = string utils . get filename("/path/to/file ");
//Error: The file name may be empty.
system . out . println(filename . length());
Optional type
Java 8 introduces optional
Optional & lt string & gtopt
//Create
opt = optional . empty();
opt = optional . of(" text ");
opt = optional . of nullable(null);
//Judge and read
if (opt.isPresent()) {
opt . get();
}
//Default value
opt . or else(" default ");
opt . orelseget(()-& gt; "Default");
opt . orelsthrow(()-& gt; new NullPointerException());
//related operations
opt . if present(value-& gt; {
System.out.println (value);
});
Opt.filter (value-> value . length()& gt; 5);
opt . map(value-& gt; value . trim());
opt . flat map(value-& gt; {
string trimmed = value . trim();
Return trimmed.isEmpty ()? optional . empty():optional . of(trimmed);
});
The chain call of method can easily lead to null pointer exception, but if the return values are all wrapped in Optional, you can use flatMap method to realize safe chain call:
String zipCode = getUser()
. Plan (User::getAddress)
. Floor plan (address: getZipCode)
. orElse(" ");
The Java 8 stream API also uses Optional as the return type:
stringList.stream()。 findFirst()。 OrElse ("default");
stringList.stream()
. max(Comparator.naturalOrder())
. if present(system . out::println);
In addition, Java 8 also provides separate optional classes for basic types, such as OptionalInt and OptionalDouble, which are very suitable for scenes with high performance requirements.
Null pointer exception in other JVM languages
The Option class in Scala language can be optional for Java 8. It has two subtypes, some representing values, but not representing null values.
val opt:Option[String]= Some(" text ")
opt.getOrElse("default ")
In addition to judging with the option #isEmpty, you can also use Scala's pattern matching:
Select match {
case Some(text)= & gt; Print (text)
Case None = & gtprintln ("default")
Scala's collection processing function library is very powerful, and Option can be directly operated as a collection, such as filer, map, for-analysis:
opt.map(_。 Trim). Filter (_). Length & gt0). Map (_. toUpperCase)。 getOrElse("DEFAULT ")
val upper = for {
text & lt- opt
Trim & lt- Some(text.trim ())
Upper & lt- some (trimmed), if trimmed. 0
} upper limit of yield
upper.getOrElse("DEFAULT ")
Kotlin uses another way, and users need to clearly distinguish nullable types from non-nullable types when defining variables. When nullable types are used, null value detection must be performed.
var a: String = "text "
A = null // Error: Cannot assign null to a non-empty string type.
Val b: string? = "Text"
//Error: You must use the security operator (? . ) or force to ignore (! ! . )。
Print length
val l: Int? = b? . Length//Safe operation
b! ! . Length // Force ignore, which may throw a null exception.
One of the characteristics of Kotlin is interoperability with Java, but Kotlin compiler cannot know whether the Java type is empty, so it is necessary to use comments in Java code, and Kotlin supports a wide range of comments. Since Spring Framework 5.0, Kotlin has been supported natively, and its null value detection is also carried out through comments, so Kotlin can safely call all APIs of Spring Framework.
conclusion
In the above scheme, I recommend using comments to prevent null pointer exceptions, because this method is very effective and less harmful to the code. All public * * *** API should be annotated with @Nullable and @NonNull, which can force the caller to prevent null pointer exceptions and make our program more robust.