Why Printing a null Object in Java Does Not Throw an Exception
This article explores Java's handling of null references when printed or concatenated, showing how PrintStream.print and StringBuilder.append convert null values to the literal string "null" without raising exceptions, and walks through the underlying source code and bytecode.
In Thinking in Java the author notes that primitive fields are initialized to zero while object references are initialized to null , and that printing a null reference does not cause an exception. Curious about this behavior, the article investigates the JDK source to explain why.
The investigation is divided into three questions.
First question
What happens when a String variable that is null is printed?
String s = null;
System.out.print(s);The output is the literal text null . The source of PrintStream.print(String s) shows a simple null‑check:
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}Second question
What about printing a non‑String object such as Integer that is null ?
Integer i = null;
System.out.print(i);The result is again null . The overload PrintStream.print(Object obj) delegates to String.valueOf(obj) :
public void print(Object obj) {
write(String.valueOf(obj));
}And String.valueOf(Object obj) returns "null" when the argument is null :
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}Thus both String and non‑String nulls are safely converted to the literal "null" before printing.
Third question (the hidden "main course")
What is the result of concatenating a null reference with a string?
String s = null;
s = s + "!";
System.out.print(s);The output is null! . The + operator is compiled to use StringBuilder :
L0
ACONST_NULL
ASTORE 1
L1
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.
()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "!"
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 1
L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.print(Ljava/lang/String;)VThe relevant StringBuilder.append methods handle null values by calling appendNull() , which appends the characters "null" to the builder:
// for String
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
// ...
}
// for Object
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
private AbstractStringBuilder appendNull() {
// appends the characters 'n','u','l','l'
// ...
return this;
}Consequently, concatenating a null reference with a string yields the literal "null" followed by the other string.
Conclusion
The article demonstrates that Java’s PrintStream.print overloads and StringBuilder.append contain explicit null‑handling logic that converts a null reference to the string "null" rather than throwing a NullPointerException . Understanding these mechanisms helps developers control null behavior in their programs.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.