/** * 拼接字符串 * * @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
, 因此这里并不会抛出空指针异常。