java · 12 5 月, 2021 0

JAVA中String字符串如何处理拼接null

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