Concatenating null strings in Java
Why must it work?
The JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 "String Concatenation Operator +", leading to JLS 8, § 5.1.11 "String Conversion", requires this operation to succeed without failure:
...Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
How does it work?
Let's look at the bytecode! The compiler takes your code:
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
and compiles it into bytecode as if you had instead written this:
String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"
(You can do so yourself by using javap -c
)
The append methods of StringBuilder
all handle null just fine. In this case because null
is the first argument, String.valueOf()
is invoked instead since StringBuilder does not have a constructor that takes any arbitrary reference type.
If you were to have done s = "hello" + s
instead, the equivalent code would be:
s = new StringBuilder("hello").append(s).toString();
where in this case the append method takes the null and then delegates it to String.valueOf()
.
Note: String concatenation is actually one of the rare places where the compiler gets to decide which optimization(s) to perform. As such, the "exact equivalent" code may differ from compiler to compiler. This optimization is allowed by JLS, Section 15.18.1.2:
To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
The compiler I used to determine the "equivalent code" above was Eclipse's compiler, ecj.
What happens when string is concatenated with null?
null
is not an operator. null
is a literal that represents a null
reference, one that does not refer to any object. null
is the default value of reference-type variables. It's mean that the string variable or your another object type variable is not pointing to anywhere in the memory.
And when you concatenate it with another string. It will added to that string. why? because If the reference is null
, it is converted to the string "null"
.
String s1=null;
String s2="";
System.out.println(s1);
System.out.println(s2);
s1=s1+"jay";
s2=s2+"jay";
// compiler convert these lines like this,
// s1 = (new StringBuilder()).append((String)null).append("jay").toString();
// s2 = (new StringBuilder()).append((String)"").append("jay").toString();
System.out.println(s1);
System.out.println(s2);
It will print nulljay
What is the right approach to concatenating a null String in Java?
The most concise solution this is:
System.out.println("s: " + (s == null ? "" : s));
or maybe create or use a static helper method to do the same; e.g.
System.out.println("s: " + denull(s));
However, this question has the "smell" of an application that is overusing / misusing null
. It is better to only use / return a null
if it has a specific meaning that is distinct (and needs to be distinct) from the meanings of non-null values.
For example:
- If these nulls are coming from String attributes that have been default initialized to
null
, consider explicitly initializing them to""
instead. - Don't use
null
to denote empty arrays or collections. - Don't return
null
when it would be better to throw an exception. - Consider using the Null Object Pattern.
Now obviously there are counter-examples to all of these, and sometimes you have to deal with a pre-existing API that gives you nulls ... for whatever reason. However, in my experience it is better to steer clear of using null
... most of the time.
So, in your case, the better approach may be:
String s = ""; /* instead of null */
System.out.println("s: " + s);
String concatenation with Null
Because Java converts the expression "A String" + x
to something along the lines of "A String" + String.valueOf(x)
In actual fact I think it probably uses StringBuilder
s, so that:
"A String " + x + " and another " + y
resolves to the more efficient
new StringBuilder("A String ")
.append(x)
.append(" and another ")
.append(y).toString()
This uses the append
methods on String builder (for each type), which handle null
properly
Why String concatenate null with + operator and throws NullPointerException with concate() method
Case 1:
System.out.println(strNull+str); // will not give you exception
From the docs(String conversion)
If the reference is null, it is converted to the string "null" (four
ASCII characters n, u, l, l).Otherwise, the conversion is performed as if by an invocation of the
toString method of the referenced object with no arguments; but if the
result of invoking the toString method is null, then the string "null"
is used instead.
Case 2:
str.concat(strNull); //NullPointer exception
If you see the source of concat(String str)
it uses str.length();
so it would be like null.length()
giving you a NullPointerException
.
Concatenate string values with delimiter handling null and empty strings?
String joined =
Stream.of(val1, val2, val3, val4)
.filter(s -> s != null && !s.isEmpty())
.collect(Collectors.joining(","));
Java String concatenation - nulls
"String conversion," required by the concatenation operator, mandates that null values are to be mapped to the four characters null
whenever a string representation is needed.
Spec for string conversion: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.11
Spec for string concatenation: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.18.1
Getting 'null' when concatenating chars into string array
stringArr[i] += "";
this line is causing the issue, which is equivalent tostringArr[i] = stringArr[i]+ "";
you are declaring a null string and appending a empty string to it, simply change it to
stringArr[i] = "";
Concatenation of a null String object and a string literal
This line:
String concatenated = str2 + " a_literal_string";
is compiled into something like
String concatenated = new StringBuilder().append(str2)
.append(" a_literal_string")
.toString();
This gives "null a_literal_string"
(and not NullPointerException
) because StringBuilder.append
is implemented using String.valueOf
, and String.valueOf(null)
returns the string "null"
.
I tried also to concatenate an Integer initialized to null and the string literal "a_literal_string" and I've got the same thing
This is for the same reason as above. String.valueOf(anyObject)
where anyObject
is null
will give back "null"
.
Why am I able to concatenate a String to a null String but not a Character to a null Character?
Java uses autoboxing (actually, in this case, unboxing) to convert the Character
object to a char
primitive and it fails since nullCharacter
is null.
Autoboxing only affects classes that wrap primitives and so it does not apply to String
.
If you convert the not-null Character
(named character
in your code) to a String
, you will not get NullPointerException
.
System.out.println(character.toString() + nullCharacter);
Related Topics
How to Override Class Variables in Java
How to Gracefully Handle the Sigkill Signal in Java
How to Find Files That Match a Wildcard String in Java
Regex Doesn't Work in String.Matches()
Spring: @Component Versus @Bean
Using Env Variable in Spring Boot's Application.Properties
Is There a Destructor for Java
Java: How to Start a Standalone Application from the Current One When Both Are in the Same Package
How to Create a Rest Client for Java
How to Get the File Extension of a File in Java
Java Io Implementation of Unix/Linux "Tail -F"
Java, Classpath, Classloading => Multiple Versions of the Same Jar/Project
Obtaining a Powerset of a Set in Java
The Case Against Checked Exceptions
Which Is More Efficient, a For-Each Loop, or an Iterator