Concatenating Null Strings in Java

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 StringBuilders, 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 to
stringArr[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



Leave a reply



Submit