Core Java

When null checking miserably fails

Disclaimer

Before going on I have to state that the techniques described in this article serve no practical purpose when we program Java. It is like a crossword or puzzle. It main train your brain in logical thinking, may develop your Java language knowledge or even your thinking skills. It is like a trick a magician performs. At the end you realize that nothing is what it looks like. Never do such tricks in real life programming that you may need to apply to solve this mind twister.
 
 
 

The Problem

I recently read an article that described the debugging case when:

if(trouble != null && !trouble.isEmpty()) {
  System.out.println(“fine here: ” + trouble);
  }else{
  System.out.println(“not so fine here: ” + trouble);
}

was printing out:

fine here: null

The actual bug was that the string contained “null”, a.k.a. the characters ‘n’, ‘u’, ‘l’ and ‘l’. May happen in real life especially when you concatenate strings without checking the nullity of a variable.

Then I started to think about other similar strange code and debug situation. Could I make it so that the variable is not only “null” string with these characters but really null? Seems to be crazy? Have a look at the code:

package com.javax0.blog.nullisnotnull;

public class NullIsNotNull {

	public static void troubled(){
		String trouble = new String("hallo");
		Object z = trouble != null && !trouble.toString().isEmpty() ? 
                                                          trouble.toString() : "";
		if (z == null) {
			System.out.println("z is really " + z + "?");
		}
	}
}

Will it ever print out the:

z is really null?

question. The fact is that you can create a Java class containing a public static void main() so that starting that class as a Java application the sentence will be printed when main() invokes the method troubled(). In other words: I really invoke the method troubled() and the solution is not that main() prints the sentence.

In this case the variable z is not only printed as “null” but it really is null.

Hints

The solution should not involve

  • reflection
  • byte code manipulation
  • calling JNI
  • special class loaders
  • java agent
  • annotation processor

These are too heavy tools. You do not need such armory for the purpose.

Hint #1

If I change the code so that the variable z is String it does not even compile:

This is what I see in Eclipse
This is what I see in Eclipse

 

If it confused you even more, then sorry. Read on!

Hint #2

In the Java language String is an identifier and not a keyword. The Java Language Specification section 3.9 may give more information on the significance of this.

Hint #3

The method toString() in class Object has a return type java.lang.String. You may want to read my article about the difference between the name, simple name and canonical name of a class. It may shed some light and increase the hit count of the article.

Hint #4

To use a class declared in the same package you need not import that package.

Solution

The solution is to create a class named String in the same package. In that case the compiler will use this class instead of java.lang.String. The ternary operator in the code is simple magician trick. Something to diverge your attention from the important point. The major point is that String is not java.lang.String in the code above. If you still can not find out how to create the trick class, click on the collapsed source code block to see it in all glory:

package com.javax0.blog.nullisnotnull;

class String {
	private java.lang.String jString;
	private boolean first = true;

	public String(java.lang.String s) {
		jString = s;
	}

	public boolean isEmpty() {
		return jString.isEmpty();
	}

	@Override
	public java.lang.String toString() {
		if( first ){
			first = false;
			return jString;
		}
		return null;
	}

	public static void main(java.lang.String[] args) {
		NullIsNotNull.troubled();
	}
}
Reference: When null checking miserably fails from our JCG partner Peter Verhas at the Java Deep blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Tushar Goel
Tushar Goel
9 years ago

Hi Peter,

I dont find any problem in compiling the code you mentioned in Hint#1.

public class TestClass {

public TestClass() {

}

public static void main(String[] args) {
String trouble = new String(“hello”);

String z = trouble != null
&& !trouble.toString().isEmpty()
? trouble.toString()
: “”;

if (z == null) {
System.out.println(“z is really ” + z +”?”);
} else {
System.out.println(“z is ” + z);
}
}
}

output: z is hello

Nitish
Nitish
6 years ago

I do not think this case will ever occur in real application.

Back to top button