/**
* 拼接字符串
*
* @author xianglujun
* @date 2021/5/12 14:31
* @since 1.4.4
*/
public class StringConcatTest {
@Test
public void testConcat() {
System.out.println("" + null);
}
}
在以上的输出中,最终输出结果为null.
这个地方的并没有抛出NullPointerException的错误, 这个需要通过查看字节码的方式,查看原因:
通过执行java -p StringConcatTest.class , 得到以下结果:
Classfile /E:/hz/projects/CICD/titan-cc-core/titan-cc-core-server/target/test-classes/com/huize/titan/StringConcatTest.class
Last modified 2021-5-12; size 803 bytes
MD5 checksum ec09bcdbb824e5a404d4da46e2106992
Compiled from "StringConcatTest.java"
public class com.huize.titan.StringConcatTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #11.#24 // java/lang/Object."<init>":()V
#2 = Fieldref #25.#26 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Class #27 // java/lang/StringBuilder
#4 = Methodref #3.#24 // java/lang/StringBuilder."<init>":()V
#5 = String #28 //
#6 = Methodref #3.#29 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#7 = Methodref #3.#30 // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
#8 = Methodref #3.#31 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#9 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/lang/String;)V
#10 = Class #34 // com/huize/titan/StringConcatTest
#11 = Class #35 // java/lang/Object
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Lcom/huize/titan/StringConcatTest;
#19 = Utf8 testConcat
#20 = Utf8 RuntimeVisibleAnnotations
#21 = Utf8 Lorg/junit/Test;
#22 = Utf8 SourceFile
#23 = Utf8 StringConcatTest.java
#24 = NameAndType #12:#13 // "<init>":()V
#25 = Class #36 // java/lang/System
#26 = NameAndType #37:#38 // out:Ljava/io/PrintStream;
#27 = Utf8 java/lang/StringBuilder
#28 = Utf8
#29 = NameAndType #39:#40 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#30 = NameAndType #39:#41 // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
#31 = NameAndType #42:#43 // toString:()Ljava/lang/String;
#32 = Class #44 // java/io/PrintStream
#33 = NameAndType #45:#46 // println:(Ljava/lang/String;)V
#34 = Utf8 com/huize/titan/StringConcatTest
#35 = Utf8 java/lang/Object
#36 = Utf8 java/lang/System
#37 = Utf8 out
#38 = Utf8 Ljava/io/PrintStream;
#39 = Utf8 append
#40 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#41 = Utf8 (Ljava/lang/Object;)Ljava/lang/StringBuilder;
#42 = Utf8 toString
#43 = Utf8 ()Ljava/lang/String;
#44 = Utf8 java/io/PrintStream
#45 = Utf8 println
#46 = Utf8 (Ljava/lang/String;)V
{
public com.huize.titan.StringConcatTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 12: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/huize/titan/StringConcatTest;
public void testConcat();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: ldc #5 // String
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aconst_null
16: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
19: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: return
LineNumberTable:
line 16: 0
line 17: 25
LocalVariableTable:
Start Length Slot Name Signature
0 26 0 this Lcom/huize/titan/StringConcatTest;
RuntimeVisibleAnnotations:
0: #21()
}
SourceFile: "StringConcatTest.java"
通过查看字节码,JDK在处理 + 处理字符串拼接的时候,通过StringBuilder.append() 进行处理,通过查看源码:
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
在拼接字符串的时候,最终是通过执行Stirng.valueOf 将对象处理为字符串对象, 在String中,对应源码如下:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
最终会返回null, 因此这里并不会抛出空指针异常。