Why Printing a Null Object in Java Does Not Throw an Exception
This article explains why Java's print methods output the literal "null" instead of throwing a NullPointerException, by examining the source code of PrintStream.print for both String and Object arguments, the behavior of String.valueOf, and the compiler‑generated StringBuilder handling of null during concatenation.
In Thinking in Java it is noted that primitive fields are auto‑initialized to zero while object references are initialized to null , and that calling methods on a null reference throws a NullPointerException, but printing a null reference does not.
The article investigates why printing a null object does not raise an exception, breaking the question into three sub‑problems.
First problem – printing a null String
String s = null;
System.out.print(s);The output is the literal null . Looking at the source of PrintStream.print(String s) shows a simple null check that substitutes the string "null" before writing:
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}Second problem – printing a null non‑String object (e.g., Integer )
Integer i = null;
System.out.print(i);The result is also null . The overload PrintStream.print(Object obj) delegates to String.valueOf(obj) :
public void print(Object obj) {
write(String.valueOf(obj));
}String.valueOf(Object obj) returns "null" when the argument is null, otherwise it calls obj.toString() :
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}Third problem – 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(String)Ljava/lang/StringBuilder; LDC "!" INVOKEVIRTUAL java/lang/StringBuilder.append(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(String)V When StringBuilder.append(String) receives a null argument it calls appendNull() , which appends the characters "null" to the builder: public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } private AbstractStringBuilder appendNull() { int c = count; ensureCapacityInternal(c + 4); value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; count = c; return this; } Thus, both the print methods and the string concatenation logic explicitly handle null values by converting them to the literal "null", preventing a NullPointerException. In summary, Java’s standard library and compiler insert safeguards that replace null references with the string "null" when printing or concatenating, which explains the observed behavior.
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.