Why do I get an exception when passing null constant but not when passing a null string reference?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
This behavior is usually caused by Java overload resolution, not by null having two different meanings. The key detail is that the compiler chooses an overloaded method based on the compile-time type of the argument expression, and the literal null has no specific reference type until overload resolution gives it one.
The Classic Example: String.valueOf
A well-known case is String.valueOf. It has several overloads, including one that accepts Object and one that accepts char[].
Now compare these two calls:
The first line prints null. The second line throws a NullPointerException.
That looks inconsistent until you look at which overload Java chooses.
Why String.valueOf(s) Works
When s is declared as String, the compiler knows the expression has type String. String is compatible with Object, but it is not compatible with char[]. That means the compiler selects:
That overload is null-safe. Internally it behaves like this idea:
So a null String reference is still passed to the Object overload, and the result is the literal text null.
Why String.valueOf(null) Throws
The literal null is special. It can be assigned to any reference type, including Object and char[]. During overload resolution, Java picks the most specific applicable overload.
Between Object and char[], char[] is more specific because an array type is a subtype of Object. So this call:
is compiled as if you had written:
The char[] overload expects an array and eventually reads from it. Because the array reference is null, that path throws NullPointerException.
You can see the difference explicitly:
The first two calls return null as text. The last call throws.
Compile-Time Type Controls Overload Selection
The important rule is that overload selection happens at compile time. Java does not look at what the value happens to be at runtime and then decide again. It only uses the declared type of the expression.
For example:
This prints:
print(null) chooses the most specific overload among the applicable methods, which is print(String) here.
How To Avoid The Surprise
If you want predictable behavior, make the intended overload explicit with a cast or by assigning the value to a variable with the desired compile-time type.
This matters whenever a Java API has overloads for unrelated or differently behaving reference types. If one overload is null-safe and another is not, the null literal may select the wrong one for your intention.
Another practical approach is to use a null check before calling the overloaded method:
That is more verbose, but it removes overload-resolution ambiguity from the code path entirely.
A Broader Lesson About APIs
When reading a method signature list, do not assume null will go to the overload you mentally group as the general-purpose one. The compiler follows type specificity rules, not intent. This is especially relevant for overloaded factory methods, logging methods, and utility methods that accept arrays, objects, or varargs.
If a method call involving null behaves strangely, inspect the overloads first. The exception is often not about null handling at all; it is about choosing a different method than you expected.
Common Pitfalls
- Assuming the literal
nullbehaves the same as a variable that currently contains null. - Forgetting that overload resolution uses compile-time types, not runtime values.
- Ignoring more specific overloads such as
char[],String, or varargs methods. - Treating
String.valueOf(null)as equivalent toString.valueOf((Object) null). - Writing overloaded APIs where different reference-type overloads handle null very differently.
Summary
- The
nullliteral has no fixed reference type until overload resolution chooses one. - Java picks the most specific applicable overload at compile time.
- '
String.valueOf(s)withString s = nullcalls theObjectoverload and returns"null".' - '
String.valueOf(null)can select thechar[]overload, which throwsNullPointerException.' - Use casts or explicit variables when you need a specific overload.

