preface

The String type is an amazing thing that is prone to confusing errors. String concatenation (String concatenation) : String concatenation (String concatenation)

Take this code for example:

String s = null;
s = s + "hello";
System.out.println(s + " world");
Copy the code

You might expect the result to be “Hello World,” but the actual result is “NullHello World,” amazing.

In fact, this is nothing, practice will see the results. But when your curiosity gets the better of you and you search the Internet for why, you may get the wrong answer.

When I searched, I saw thousands of articles with incorrect explanations. To eliminate a few misdirect, analyze reason for everybody specially.

Cause analysis of errors

If you do a search on the above questions, you might see answers like:

S +" world" is equivalent to s = string.valueof (s)+"word";Copy the code

We then attach the valueOf method:

Public static String valueOf(Object obj) {return (obj == null)? "null" : obj.toString(); }Copy the code

Did you buy it? If you do, you might be wrong. Here’s why.

Optimization of the Java compiler

We know that the Java compiler makes some optimizations for us when we write the following code:

String a = "Hello ";
String b = "World";
System.out.println(a + b);
Copy the code

How is it optimized? This code, optimized by the compiler, is equivalent to:

StringBuilder sb = new StringBuilder();
sb.append("Hello ");
sb.append("World");
String result = sb.toString();
System.out.println(result);
Copy the code

That is, the plus operation is optimized for StringBuilder based operations, not the string.Valueof operation mentioned above.

Null above is equivalent to the following operation:

StringBuilder sb = new StringBuilder(null);
sb.append("hello");
sb.append(" world");
String result = sb.toString();
System.out.println(result);
Copy the code

AbstractStringBuilder (null) : null (null); null (null);

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;
}
Copy the code

The corresponding appendNull method is implemented as:

private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;
}
Copy the code

Null is treated as the string “null” in appendNull. This is why null appears in the concatenation.

Bytecode tracing

For the example above, if you want to see how the compiler handles this, you can use the javap -c command to see the corresponding bytecode:

As can be seen from bytecode, it is basically consistent with the above analysis. Therefore, it is better to have no books than to have all faith.

Expand the problem

What if we simply print null?

String s = null;
System.out.println(s);
Copy the code

When I execute the above program, the console prints null. Where does this null come from? Look directly at the underlying implementation of println:

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}
Copy the code

Finally, the print method is called, and if null, the null string is printed.

Supported, the original valueOf method has not yet appeared, so in what scenarios will valueOf method be used? For objects of type Object:

Object s = null;
String s1 = String.valueOf(s);
System.out.println(s1);
Copy the code

That is, when valueOf is explicitly called, s1 is a null string.

To expand, wrap classes for basic types such as Integer, Double, and so on:

Integer i = null;
System.out.println(i);
Copy the code

The println method is implemented as follows:

public void println(Object x) { String s = String.valueOf(x); synchronized (this) { print(s); newLine(); }}Copy the code

This means that valueOf is called on the corresponding Object. Back to the above example, if Object is null, this method returns null string, and then the printer returns null.

summary

String concatenation is a very common problem, and you can accidentally add null to the concatenation. Isn’t it interesting that this situation involves optimizing the Java compiler? And as mentioned in the beginning, we also need to be dialectical about the accuracy of our answers when searching for information on the Internet.

The interview series

  • Interview questions: Talk about TCP sticky, unpack, and Solutions
  • Interview question: Why does overriding equals usually override hashCode?
  • Interviewer: How to find the longest string in a string without repetition?
  • Don’t Understand Java generics? Just use this article to make sure you have a good interview answer.
  • Interview Question: 8 Ways to Invert a string. What can you Think of?

Program new horizon

The public account “program new vision”, a platform for simultaneous improvement of soft power and hard technology, provides massive information