Java 字符串初始化

2019-02-14  本文已影响0人  yangbug

今天小伙伴和我分享一个有意思的一段代码

public static void main(string [] args){
        String str1 = "ABC";
        String str2 = "ABC";
        final String Str3 = "AB";
        String str4 = Str3 + "C";
        System.out.println(str1==str2);//true
        System.out.println(str2==str4);//true
}

final修饰Str3 是常亮时,str2 == str4

public static void main(string [] args){
        String str1 = "ABC";
        String str2 = "ABC";
        String Str3 = "AB";
        String str4 = Str3 + "C";
        System.out.println(str1==str2);//true
        System.out.println(str2==str4);//false
}

Str3为普通变量时,str2 != str4。So Why?
再看一下编译后的class文件

//Str3 为 fianl 可以看到常量池中只有 ABC,AB因为没有用到所以编译器优化了
Constant pool:
   #1 = Methodref          #6.#19         //  java/lang/Object."<init>":()V
   #2 = String             #20            //  ABC 常量池中只有ABC
   #3 = Fieldref           #21.#22        //  java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #23.#24        //  java/io/PrintStream.println:(Z)V
   #5 = Class              #25            //  A
   #6 = Class              #26            //  java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               StackMapTable
  #14 = Class              #27            //  "[Ljava/lang/String;"
  #15 = Class              #28            //  java/lang/String
  #16 = Class              #29            //  java/io/PrintStream
  #17 = Utf8               SourceFile
  #18 = Utf8               A.java
  #19 = NameAndType        #7:#8          //  "<init>":()V
  #20 = Utf8               ABC
  #21 = Class              #30            //  java/lang/System
  #22 = NameAndType        #31:#32        //  out:Ljava/io/PrintStream;
  #23 = Class              #29            //  java/io/PrintStream
  #24 = NameAndType        #33:#34        //  println:(Z)V
  #25 = Utf8               A
  #26 = Utf8               java/lang/Object
  #27 = Utf8               [Ljava/lang/String;
  #28 = Utf8               java/lang/String
  #29 = Utf8               java/io/PrintStream
  #30 = Utf8               java/lang/System
  #31 = Utf8               out
  #32 = Utf8               Ljava/io/PrintStream;
  #33 = Utf8               println
  #34 = Utf8               (Z)V
//Str3 为 普通变量 ,可以看到常量池中有 ABC AB 以及 C
Constant pool:
   #1 = Methodref          #12.#25        //  java/lang/Object."<init>":()V
   #2 = String             #26            //  ABC 
   #3 = String             #27            //  AB
   #4 = Class              #28            //  java/lang/StringBuilder
   #5 = Methodref          #4.#25         //  java/lang/StringBuilder."<init>":()V
   #6 = Methodref          #4.#29         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = String             #30            //  C
   #8 = Methodref          #4.#31         //  java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Fieldref           #32.#33        //  java/lang/System.out:Ljava/io/PrintStream;
  #10 = Methodref          #34.#35        //  java/io/PrintStream.println:(Z)V
  #11 = Class              #36            //  A
  #12 = Class              #37            //  java/lang/Object
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               main
  #18 = Utf8               ([Ljava/lang/String;)V
  #19 = Utf8               StackMapTable
  #20 = Class              #38            //  "[Ljava/lang/String;"
  #21 = Class              #39            //  java/lang/String
  #22 = Class              #40            //  java/io/PrintStream
  #23 = Utf8               SourceFile
  #24 = Utf8               A.java
  #25 = NameAndType        #13:#14        //  "<init>":()V
  #26 = Utf8               ABC
  #27 = Utf8               AB
  #28 = Utf8               java/lang/StringBuilder
  #29 = NameAndType        #41:#42        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #30 = Utf8               C
  #31 = NameAndType        #43:#44        //  toString:()Ljava/lang/String;
  #32 = Class              #45            //  java/lang/System
  #33 = NameAndType        #46:#47        //  out:Ljava/io/PrintStream;
  #34 = Class              #40            //  java/io/PrintStream
  #35 = NameAndType        #48:#49        //  println:(Z)V
  #36 = Utf8               A
  #37 = Utf8               java/lang/Object
  #38 = Utf8               [Ljava/lang/String;
  #39 = Utf8               java/lang/String
  #40 = Utf8               java/io/PrintStream
  #41 = Utf8               append
  #42 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #43 = Utf8               toString
  #44 = Utf8               ()Ljava/lang/String;
  #45 = Utf8               java/lang/System
  #46 = Utf8               out
  #47 = Utf8               Ljava/io/PrintStream;
  #48 = Utf8               println
  #49 = Utf8               (Z)V
String str4 = Str3 + "天";

首先 编译器理解C 是一个常亮,当Str3是变量时,编译器理解str4就是一个 变量 + 常量=变量,只能在运行时赋值。当Str3是常量时,编译器理解str4就是一个 常量 + 常量=常量,所以str4在处理化过程中就会预处理,在常量池中查找,并且赋值。

上一篇 下一篇

猜你喜欢

热点阅读