Released on March 17, 2020, Java has officially released JDK 14, which is now available for download. JEP 358: Helpful NullPointerExceptions JEP 358: Helpful NullPointerExceptions JEP 358: Helpful NullPointerExceptions

What’s wrong with null?

Null is a headache for Java programmers. I am constantly harassed by nullpointerExceptions. Many programmers are particularly afraid of NPE in their programs because such exceptions are often accompanied by unexpected code execution.

In programming languages, a Null Reference, similar to a Null pointer, is a declared variable that does not refer to a valid object.

Null references and NPE were included in Java 1, but Null references were actually invented by great computer scientist Tony Hoare back in 1965, originally as part of the programming language ALGOL W.

In 1965, a British computer scientist named Tony Hoare came up with the idea of null references while designing ALGOL W. ALGOL W was one of the first type languages to allocate records on the heap. Hoare chose null references “just because it’s so easy to implement.” Although he was designed to “make sure all references are perfectly safe through the compiler’s auto-detection mechanism,” he decided to green light null references because he thought it was the easiest way to model “nonexistent values.”

But in 2009, years later, he began to regret having made the decision, calling it “a billion-dollar mistake.” In fact, Hoare’s statement understates the cost to millions of programmers of the past 50 years of fixing empty references. Most modern programming languages that have emerged since ALGOL W, including Java, have been designed the same way, in order to remain compatible with older languages or, as Hoare once stated, “simply because it’s easier to implement.”

I’m sure many Java programmers hate NULL and NPE just as much, because it does cause all sorts of problems (Java 8 In Action). Such as:

  • It is the mother of error. NullPointerException is the most typical exception in Java program development today. It makes your code swell.
  • It leaves your code riddled with deeply nested null checks and horribly unreadable.
  • It is meaningless by itself. Null has no semantics of its own, especially since it represents the wrong way to model missing variable values in statically typed languages.
  • It undermines the Philosophy of Java. Java tries to keep programmers from being aware of Pointers, with one exception :null Pointers.
  • It opens a hole in Java’s type system. Null is not of any type, which means it can be assigned to any variable that references a type. This can cause problems because when the variable is passed to another part of the system, you cannot know what type the null variable was originally assigned to.

How do other languages solve the NPE problem

We know that there are many other object-oriented languages besides Java, so how do other languages solve the problem of NPE?

As in Groovy, you can access variables that may be null using the Safe Navigation Operator:

def carInsuranceName = person? .car? .insurance? .nameCopy the code

Groovy’s safe navigation operator avoids nullPointerexceptions when accessing these potentially null references, passing the null reference down the call chain when a variable in the call chain encounters a NULL, returning a NULL.

A similar feature was considered for this feature, but was later removed.

In addition, there are similar alternatives in Haskell and Scala, such as Maybe in Haskell and Option[T] in Scala.

In Kotlin, the type system strictly distinguishes whether a reference can hold NULL or not. A nullable variable must be declared. For nullable variables, a nullable variable must be nulled when accessing its members, otherwise it will not compile:

Var a: String = "ABC "a = null // compilation errorCopy the code

If allowed to be null, you can declare a nullable String as String, ok? :

var b: String? = "abc" //String? B = null // the compiler passesCopy the code

See this? Does Groovy look a bit like Groovy? But there are some differences, so I won’t expand them here.

So, back to the book, let’s take a look at what the Java language has done for NPE as a top TOIBE programming language!

What efforts Java has made

There have been some efforts to improve null and NPE.

Before Java 8 came out, Google’s Guava library was the first to provide an Optional interface to make NULL fail quickly.

Optional encapsulates objects that may be null. Optional objects contain methods that explicitly handle the presence or absence of a value. Optional classes force you to think about non-existence of a value, thus avoiding potential null pointer exceptions.

But the Optional class is not designed to completely replace NULL, it is designed to make the API easier to understand. With Optional, you can tell from the method signature that the function may return a missing value, forcing you to deal with missing values.

The use of Optional is not the focus of this article, so I will not introduce it in detail here. I often use Optional in conjunction with Stream in daily development.

Another notable addition is an enhancement to NPE in JDK 14, released recently (March 17, 2020). That’s JEP 358: Helpful NullPointerExceptions

More helpful NPE

There is an enhancement to NEP in JDK 14, and since NPE is unavoidable for now, let’s make it a little more helpful to developers.

NullPointerExceptions (NPEs) has been encountered by every Java developer. Since NPEs can occur almost anywhere in a program, trying to capture and recover from them is often impractical. As a result, developers often rely on the JVM to determine the source of the NPE when it actually occurs. For example, suppose an NPE appears in this code:

a.i = 99;
Copy the code

The JVM will print out the method, filename, and line number that caused the NPE:

Exception in thread "main" java.lang.NullPointerException
at Prog.main(Prog.java:5)
Copy the code

From the stack information above, the developer can locate the line A.i = 99 and infer that a must be null.

For more complex code, however, it is impossible to determine which variable is NULL without using a debugger. Suppose an NPE appears in this code:

a.b.c.i = 99;
Copy the code

It is impossible to determine whether a, B, or C is null at runtime.

However, after JDK14, there is a solution to this dilemma.

In JDK14, when the runtime tries to apply a NullPointerException (NPE) to a NULL object, the JVM will still throw a NullPointerException (NPE). In addition, by analyzing the program’s bytecode instructions, the JVM will determine exactly which variable is NULL. And is explicitly indicated in the stack message.

In JDK 14, if an NPE occurs in a.i = 99 above, the following stack will be printed:

Exception in thread "main" java.lang.NullPointerException: 
        Cannot assign field "i" because "a" is null
    at Prog.main(Prog.java:5)
Copy the code

If A.B.C.I. = 99; Where b is null and results in a null pointer, the following stack information is printed:

Exception in thread "main" java.lang.NullPointerException: 
        Cannot read field "c" because "a.b" is null
    at Prog.main(Prog.java:5)
Copy the code

The stack clearly indicates which object is causing the NPE, so that if an NPE occurs in an application, the developer can use the stack information to determine which object in the code is causing the NPE.

This is a small improvement in the JDK, but one that is very developer friendly. Hopefully these small and beautiful changes will become more and more common in the JDK.

References:

openjdk.java.net/jeps/358

Java 8 In Action