Friday, June 28, 2019

How to Avoid NullPointerException in Java



https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
Whenever you want a null value to be replaced with some default value instead, use MoreObjects.firstNonNull(T, T). As the method name suggests, if both of the inputs are null, it fails fast with a NullPointerException. If you are using an Optional, there are better alternatives -- e.g. first.or(second).
A couple of methods dealing with possibly-null String values are provided in Strings. Specifically, we provide the aptly named:

Google Guava isNullOrEmpty for collections
CollectionUtils.isEmpty() in commons-collections.

https://github.com/google/guava/wiki/PreconditionsExplained
https://stackoverflow.com/questions/34646554/java-util-objects-requirenonnull-vs-preconditions-checknotnull
there is one more subtle difference in general in favor of using checkNotNull which is reflected in the printf style varargs form. For example using Guava Preconditions you can do following:
public void getInput(String companyName) {
   String context = "Google";
   String moreContext = "Facebook";
   checkNotNull(companyName, "Why not try %s or %s", context, moreContext);
}
with Objects.requireNonNull you will have to do something like
public void getInput(String companyName) {
   String context = "Google";
   String moreContext = "Facebook";
   requireNonNull(companyName, "Why not try " + context + " or " + moreContext);
}
Reference: See bottom section of Preconditions Explained
Simple, varargs "printf-style" exception messages. (This advantage is also why we recommend continuing to use checkNotNull over Objects.requireNonNull introduced in JDK 7.)
EDIT: One thing to note though is that all args to the errorMessageTemplate are converted to String using String.valueOf(arg) so you can use only %s and not other type specifiers like %d or %f etc.
https://shipilev.net/blog/2016/arrays-wisdom-ancients/

https://medium.com/@hanru.yeh/collection-toarray-new-t-0-will-be-faster-than-collection-toarray-new-t-size-5b129fabfa88



Vectorized arraycopy in the Object[] toArray() case is much faster than the type-checked arraycopy in toArray(new T[size]) and toArray(new T[0]). Alas, that does not help us if we want to get T[].
toArray(new T[0]) seems faster, safer, and contractually cleaner, and therefore should be the default choice now.

https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
Item 54: Return empty collections or arrays, not nulls
Never return null instead of a zero-length array
Do not preallocate the array passed to toArray in hopes of improving performance. Studies have shown that it is counterproductive [Shipilëv16]:

// Don’t do this - preallocating the array harms performance! return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);

https://wiki.sei.cmu.edu/confluence/display/java/ERR08-J.+Do+not+catch+NullPointerException+or+any+of+its+ancestors
https://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

https://www.javaworld.com/article/2072719/effective-java-nullpointerexception-handling.html
https://crunchify.com/have-you-noticed-nullpointerexception-npe-there-are-few-best-practices-to-avoid-npe/
Try to use containsKey()containsValue()contains() checks.
Check if String is null of empty after trim() operation
https://courses.cs.washington.edu/courses/cse331/12sp/lectures/sect08-nullness-type.pdf
https://www.geeksforgeeks.org/null-pointer-exception-in-java/
  • Invoking a method from a null object.
  • Accessing or modifying a null object’s field.
  • Taking the length of null, as if it were an array.
  • Accessing or modifying the slots of null object, as if it were an array.
  • Throwing null, as if it were a Throwable value.
  • When you try to synchronize over a null object.
https://en.wikibooks.org/wiki/Java_Programming/Preventing_NullPointerException
Comparing string variable with a string literal

Check all references obtained from 'untrusted' methods
File.listFiles() can return null if /etc is not a directory.

For each loop trap

1. [Mandatory] Do not catch Runtime exceptions defined in JDK, such as NullPointerException and IndexOutOfBoundsException. Instead, pre-check is recommended whenever possible.
  1. Invoking methods on an object which is not initialized
  2. Parameters passed in a method are null
  3. Calling toString() method on object which is null
  4. Comparing object properties in if block without checking null equality
  5. Incorrect configuration for frameworks like spring which works on dependency injection
  6. Using synchronized on an object which is null
  7. Chained statements i.e. multiple method calls in a single statement

3.4. Consider Primitives Rather than Objects

Null problem occurs where object references points to nothing. So it is always safe to use primitives as much as possible because they does not suffer with null references. All primitives must have some default values also attached so beware of it.

3.5. Carefully Consider Chained Method Calls

While chained statements are nice to look at in the code, they are not NPE friendly. A single statement spread over several lines will give you the line number of the first line in the stack trace regardless of where it occurs.
ref.method1().method2().method3().methods4();
These kind of chained statement will print only “NullPointerException occurred in line number xyz”. It really is hard to debug such code. Avoid such calls.

3.6. Use String.valueOf() Rather than toString()

3.8. Discourage Passing of Null Parameters

I have seen some method declarations where method expects two or more parameters. If one of parameter is passed as null, then also method works if some different manner. Avoid this.
In stead you should define two methods; one with single parameter and second with two parameters. Make parameters passing mandatory. This helps a lot when writing application logic inside methods because you are sure that method parameters will not be null; so you don’t put unnecessary assumptions and assertions.

4.1. instanceof operator

The instanceof operator is NPE safe. So, instanceof null always returns false. It does not cause a NullPointerException. You can eliminate messy conditional code if you remember this fact.
// Unnecessary code
if (data != null && data instanceof InterestingData) {
}
// Less code. Better!!
if (data instanceof InterestingData) {
}

https://blog.indrek.io/articles/chaining-optionals-in-java-8/

https://javarevisited.blogspot.com/2013/05/ava-tips-and-best-practices-to-avoid-nullpointerexception-program-application.html
1) Call equals() and equalsIgnoreCase() method on known String literal rather unknown object
Always call equals() method on known String which is not null. Since equals() method is symmetriccalling a.equals(b) is same as calling b.equals(a), and that’s why many programmer don’t pay attention on object a and b. One side effect of this call can result in NullPointerException, if caller is null.


2) Prefer valueOf() over toString() where both return same result


Read more: https://javarevisited.blogspot.com/2013/05/ava-tips-and-best-practices-to-avoid-nullpointerexception-program-application.html#ixzz5sBY0CqJu


Read more: https://javarevisited.blogspot.com/2013/05/ava-tips-and-best-practices-to-avoid-nullpointerexception-program-application.html#ixzz5sBWtRMcl


https://dzone.com/articles/java-8-optional-avoid-null-and

https://stackify.com/optional-java/
https://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/









Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
    System.out.println(outer.nested.inner.foo);
}

We can get rid of all those null checks by utilizing the Java 8 Optional type. The method map accepts a lambda expression of type Function and automatically wraps each function result into an Optional. That enables us to pipe multiple map operations in a row. Null checks are automatically handled under the hood.









Optional.of(new Outer())
    .map(Outer::getNested)
    .map(Nested::getInner)
    .map(Inner::getFoo)
    .ifPresent(System.out::println);

An alternative way to achieve the same behavior is by utilizing a supplier function to resolve the nested path:









Outer obj = new Outer();
resolve(() -> obj.getNested().getInner().getFoo());
    .ifPresent(System.out::println);

Calling obj.getNested().getInner().getFoo()) might throw a NullPointerException. In this case the exception will be caught and the method returns Optional.empty().









public static <T> Optional<T> resolve(Supplier<T> resolver) {
    try {
        T result = resolver.get();
        return Optional.ofNullable(result);
    }
    catch (NullPointerException e) {
        return Optional.empty();
    }
}

http://javahowto.blogspot.com/2006/07/not-your-typical-npe.html
You may have noticed it's the autoboxing, the implicit cast from Integer to int that has caused NPE. This line
?
1
int version = project.getVersion();
is really this at runtime:


?
1
int version = project.getVersion().intValue();
https://dzone.com/articles/autoboxing-and-its-pitfalls-1
Autoboxing does create objects which are not clearly visible in the code. So when autoboxing occurs performance suffers. If you see the Javadocs:

It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate it.

Confused Equals

Autoboxing has brought with itself a lot of things that just are not obvious to a programmer. What would be the output of below code?
Long longWrapperVariable=2L ;
System.out.println(longWrapperVariable.equals(2));
System.out.println(longWrapperVariable.equals(2L));
Here is what the above code prints:
false
true
If you are wondering what happened above, 2 was boxed to Integer and henceequals could not compare it with Long. And 2L was boxed to Long and hence returned true.
Here is simple example that demonstrates the caching of int:
System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
What would be the result of above code?
true
false

Ambiguous Method Calls

What would be the result of below code?
public static void main(String[] args) throws Exception {
int test = 20;
myOverloadedFunction(test);
}
static void myOverloadedFunction(long parameter) {
System.out.println("I am primitive long");
}
static void myOverloadedFunction(Integer parameter) {
System.out.println("i am wrapper class Integer");
}
And the output is:
I am primitive long
The answer is that the compiler will choose widening over boxing, so the output will be “I am primitive long.”

NullPointerException

  While running the below code, NullPointerException(NPE) can be thrown and it is not quite obvious from the code if you are not aware of autoboxing. Eclipse will show the warning for this code, “Null pointer access: This expression of type Boolean is null but requires auto-unboxing.” Because I made it obvious to eclipse that testNPEvariable is null.
Boolean testNPE = null;   
if(testNPE){
 System.out.println("will never reach here");
}

2. Mixing primitive and wrapper in relational or equality operator

If we use a wrapper object to compare against a primitive using relational operator (like “<" or ">“) the unboxing of that wrapper can cause NullPointerException.
Widening VS Boxing
Widening is transforming a variable to another with a wider type. For example String -> Objectbyte -> intint -> long etc. If overloading comes in a case where one method has “widened” parameter and other method has “boxed” parameter then the Widening takes priority than boxing, in other words Widening beats boxing. An example program is given below.

http://seanyeh.com/pages/java_autoboxing_null_pointer_exception/
Before Java 1.5, you had to manually convert the wrapper class to its primitive form by calling a specific function. For example, if you created an ArrayList of Integers, you would need to call the intValue() function on the Integer object to get the primitive value
int x = arr.get(0); // Wrong, will give you an error
int x = arr.get(0).intValue(); // Correct!
With autoboxing/unboxing, Java will implicitly call these functions (such as intValue) from the wrapper classes when it notices you are trying to use the primitive value.
Normally, map.get(x) will return a Boolean object, but will also return null if x is not found in the HashMap. Note that null is a valid value for a Boolean object (or any Java object)
However, Java sees that I'm comparing a Boolean object with a boolean primitive, so it implicitly calls the Boolean object's booleanValue() function.
Because map.get(x) returns null, Java is actually implicitly calling booleanValue() on the null object, hence the NullPointerException!

Solution

The solution is to check if the object is null before performing a comparison
if( map.get("a") != null && map.get("a") == true )
    // do something
or, more simply,
if( map.get("a") != null && map.get("a") )

https://checkerframework.org/manual/#nullness-checker
The most important annotations supported by the Nullness Checker are @NonNull and @Nullable@NonNull is rarely written, because it is the default. All of the annotations are explained in Section 3.2.

The Checker Framework’s nullness annotations are similar to annotations used in other tools. You might prefer to use the Checker Framework because it has a more powerful analysis that can warn you about more null pointer errors in your code. Most of the other tools are bug-finding tools rather than verification tools, since they give up precision, soundness, or both in favor of being fast and easy to use.

If your code is already annotated with a different nullness annotation, the Checker Framework can type-check your code. It treats annotations from other tools as if you had written the corresponding annotation from the Nullness Checker


  NullPointerTester tester = new NullPointerTester();

  tester.testAllPublicStaticMethods(Range.class);
  tester.testAllPublicStaticMethods(Range.class);

  tester.testAllPublicInstanceMethods(Range.all());
  tester.testAllPublicInstanceMethods(Range.open(1, 3));

Use AbstractPackageSanityTests, ClassSanityTester or NullPointerTester 
http://shzhangji.com/blog/2018/09/20/how-to-avoid-null-pointer-exception/

@NonNull and @Nullable with Checker Framework

Checker Framework works as a plugin to the javac compiler, to provide type checks, detect and prevent various errors. Follow the official document, integrate Checker Framework with maven-compiler-plugin, and it will start to work when executing mvn compile. The Nullness Checker supports all kinds of annotations, from JSR 305 to Eclipse built-ins, even lombok.NonNull.
By default, Checker Framework applies @NonNull to all method arguments and return values. 


import org.springframework.lang.Nullable;
Checker Framework is especially useful for Spring Framework users, because from version 5.x, Spring provides built-in annotations for nullness check, and they are all over the framework code itself, mainly for Kotlin users, but we Java programmers can benefit from them, too. Take StringUtils class for instance, since the whole package is declared @NonNull, those methods with nullable argument and return values are explicitly annotated with @Nullable

https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/package-info.java
@NonNullApi
@NonNullFields
package org.springframework.util;

import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;


  Object checked = Objects.requireNonNull(arg, "arg must not be null");
We can also let Lombok generate the check for us, which will throw a more meaningful NullPointerException:
  • Use methods that already guard against null values, such as String#equalsString#valueOf, and third party libraries that help us check whether string or collection is empty.



1
2
3
4
5
6
7
8
9
10
11
12
13
if (str != null && str.equals("text")) {}
if ("text".equals(str)) {}

if (obj != null) { obj.toString(); }
String.valueOf(obj); // "null"

// from spring-core
StringUtils.isEmpty(str);
CollectionUtils.isEmpty(col);
// from guava
Strings.isNullOrEmpty(str);
// from commons-collections4
CollectionUtils.isEmpty(col);

    • For return values, if the type is Collection, return an empty collection instead of null; if it’s a single object, consider throwing an exception. This approach is also suggested by Effective Java. Good examples come from Spring’s JdbcTemplate:






    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // return new ArrayList<>() when result set is empty
    jdbcTemplate.queryForList("SELECT 1");
    
    // throws EmptyResultDataAccessException when record not found
    jdbcTemplate.queryForObject("SELECT 1", Integer.class);
    
    // works for generics
    public <T> List<T> testReturnCollection() {
      return Collections.emptyList();
    }

    @NonNull and @CheckForNull with SpotBugs

    SpotBugs is the successor of FindBugs. We can use @NonNull and @CheckForNull on method arguments or return values, so as to apply nullness check. Notably, SpotBugs does not respect @Nullable, which is only useful when overriding @ParametersAreNullableByDefault. Use @CheckForNull instead.
    To integrate SpotBugs with Maven and Eclipse, one can refer to its official document. Make sure you add the spotbugs-annotations package in Maven dependencies, which includes the nullness check annotations.






    1
    2
    3
    4
    5
    <dependency>
        <groupId>com.github.spotbugs</groupId>
        <artifactId>spotbugs-annotations</artifactId>
        <version>3.1.7</version>
    </dependency>


    Chaining of methods is a common cause of NPE, but if you have a series of methods that return Optional, you can chain them with flatMap, NPE-freely





    1
    2
    3
    4
    String zipCode = getUser()
        .flatMap(User::getAddress)
        .flatMap(Address::getZipCode)
        .orElse("");

    Java 8 Stream API also uses optionals to return nullable values. For instance:





    1
    2
    3
    4
    stringList.stream().findFirst().orElse("default");
    stringList.stream()
        .max(Comparator.naturalOrder())
        .ifPresent(System.out::println);

    Labels

    Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

    Popular Posts