聊聊java String的intern

发布时间:2019-11-19 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了聊聊java String的intern脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

本文主要研究一下java String的intern

String.intern()

java.base/java/lang/String.java

public final class String     implements java.io.Serializable, Comparable<String>, CharSequence,                Constable, ConstantDesc {      //......      /**      * Returns a canonical representation for the string object.      * <p>      * A pool of strings, initially empty, is maintained privately by the      * class {@code String}.      * <p>      * When the intern method is invoked, if the pool already contains a      * string equal to this {@code String} object as determined by      * the {@link #equals(Object)} method, then the string from the pool is      * returned. Otherwise, this {@code String} object is added to the      * pool and a reference to this {@code String} object is returned.      * <p>      * It follows that for any two strings {@code s} and {@code t},      * {@code s.intern() == t.intern()} is {@code true}      * if and only if {@code s.equals(t)} is {@code true}.      * <p>      * All literal strings and string-valued constant expressions are      * interned. String literals are defined in section 3.10.5 of the      * <cite>The Java&trade; Language Specification</cite>.      *      * @return  a string that has the same contents as this string, but is      *          guaranteed to be from a pool of unique strings.      * @jls 3.10.5 String Literals      */     public native String intern();      //......             }               
  • 当调用intern方法时,如果常量池已经包含一个equals此String对象的字符串,则返回池中的字符串
  • 当调用intern方法时,如果常量池没有一个equals此String对象的字符串,将此String对象添加到池中,并返回此String对象的引用(即intern方法返回指向heap中的此String对象引用)
  • 所有literal strings及string-valued constant expressions都是interned的

实例

基于jdk12

StringExistInPoolBeforeintern

public class StringExistInPoolBeforeIntern {      public static void main(String[] args){         String stringObject = new String("tomcat");         //NOTE 在intern之前,string table已经有了tomcat,因而intern返回tomcat,不会指向stringObject         stringObject.intern();         String stringLiteral = "tomcat";         System.out.println(stringObject == stringLiteral); //false     } }
  • tomcat这个literal string是interned过的,常量池没有tomcat,因而添加到常量池,常量池有个tomcat;另外由于stringObject是new的,所以heap中也有一个tomcat,而此时它指向heap中的tomcat
  • stringObject.intern()返回的是heap中常量池的tomcat;stringLiteral是tomcat这个literal string,由于常量池已经有该值,因而stringLiteral指向的是heap中常量池的tomcat
  • 此时stringObject指向的是heap中的tomcat,而stringLiteral是heap中常量池的tomcat,因而二者不等,返回false

StringNotExistInPoolBeforeIntern

public class StringNotExistInPoolBeforeIntern {      public static void main(String[] args){         String stringObject = new String("tom") + new String("cat");         //NOTE 在intern之前,string table没有tomcat,因而intern指向stringObject         stringObject.intern();         String stringLiteral = "tomcat";         System.out.println(stringObject == stringLiteral); //true     } }
  • tom及cat这两个literal string是interned过的,常量池没有tom及cat,因而添加到常量池,常量池有tom、cat;另外由于stringObject是new出来的,是tom及cat二者concat,因而heap中有一个tomcat
  • stringObject的intern方法执行的时候,由于常量池中没有tomcat,因而添加到常量池,intern()返回的是指向heap中的tomcat的引用;stringLiteral是tomcat这个literal string,由于stringObject.intern()已经将tomcat添加到常量池了并指向heap中的tomcat的引用,所以stringLiteral返回的是指向heap中的tomcat的引用
  • 由于stringLiteral返回的是指向heap中的tomcat的引用,其实就是stringObject,因而二者相等,返回true

javap

基于jdk12

StringExistInPoolBeforeIntern

javac src/main/java/com/example/javac/StringExistInPoolBeforeIntern.java javap -v src/main/java/com/example/javac/StringExistInPoolBeforeIntern.class    Last modified 2019年4月6日; size 683 bytes   MD5 checksum 207635ffd7560f1DF24b98607e2ca7db   Compiled from "StringExistInPoolBeforeIntern.java" public class com.example.javac.StringExistInPoolBeforeIntern   minor version: 0   major version: 56   flags: (0x0021) ACC_PUBLIC, ACC_SUPER   this_class: #8                          // com/example/javac/StringExistInPoolBeforeIntern   super_class: #9                         // java/lang/Object   interfaces: 0, fields: 0, methods: 2, attributes: 1 Constant pool:    #1 = Methodref          #9.#21         // java/lang/Object."<init>":()V    #2 = Class              #22            // java/lang/String    #3 = String             #23            // tomcat    #4 = Methodref          #2.#24         // java/lang/String."<init>":(Ljava/lang/String;)V    #5 = Methodref          #2.#25         // java/lang/String.intern:()Ljava/lang/String;    #6 = Fieldref           #26.#27        // java/lang/System.out:Ljava/io/PrintStream;    #7 = Methodref          #18.#28        // java/io/PrintStream.println:(Z)V    #8 = Class              #29            // com/example/javac/StringExistInPoolBeforeIntern    #9 = Class              #30            // java/lang/Object   #10 = Utf8               <init>   #11 = Utf8               ()V   #12 = Utf8               Code   #13 = Utf8               LineNumberTable   #14 = Utf8               main   #15 = Utf8               ([Ljava/lang/String;)V   #16 = Utf8               StackMapTable   #17 = Class              #31            // "[Ljava/lang/String;"   #18 = Class              #32            // java/io/PrintStream   #19 = Utf8               SourceFile   #20 = Utf8               StringExistInPoolBeforeIntern.java   #21 = NameAndType        #10:#11        // "<init>":()V   #22 = Utf8               java/lang/String   #23 = Utf8               tomcat   #24 = NameAndType        #10:#33        // "<init>":(Ljava/lang/String;)V   #25 = NameAndType        #34:#35        // intern:()Ljava/lang/String;   #26 = Class              #36            // java/lang/System   #27 = NameAndType        #37:#38        // out:Ljava/io/PrintStream;   #28 = NameAndType        #39:#40        // println:(Z)V   #29 = Utf8               com/example/javac/StringExistInPoolBeforeIntern   #30 = Utf8               java/lang/Object   #31 = Utf8               [Ljava/lang/String;   #32 = Utf8               java/io/PrintStream   #33 = Utf8               (Ljava/lang/String;)V   #34 = Utf8               intern   #35 = Utf8               ()Ljava/lang/String;   #36 = Utf8               java/lang/System   #37 = Utf8               out   #38 = Utf8               Ljava/io/PrintStream;   #39 = Utf8               println   #40 = Utf8               (Z)V {   public com.example.javac.StringExistInPoolBeforeIntern();     descriptor: ()V     flags: (0x0001) 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 8: 0    public static void main(java.lang.String[]);     descriptor: ([Ljava/lang/String;)V     flags: (0x0009) ACC_PUBLIC, ACC_STATIC     Code:       stack=3, locals=3, args_size=1          0: new           #2                  // class java/lang/String          3: dup          4: ldc           #3                  // String tomcat          6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V          9: astore_1         10: aload_1         11: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;         14: pop         15: ldc           #3                  // String tomcat         17: astore_2         18: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;         21: aload_1         22: aload_2         23: if_acmpne     30         26: iconst_1         27: goto          31         30: iconst_0         31: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V         34: return       LineNumberTable:         line 11: 0         line 13: 10         line 14: 15         line 15: 18         line 16: 34       StackMapTable: number_of_entries = 2         frame_type = 255 /* full_frame */           offset_delta = 30           locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]           stack = [ class java/io/PrintStream ]         frame_type = 255 /* full_frame */           offset_delta = 0           locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]           stack = [ class java/io/PrintStream, int ] } SourceFile: "StringExistInPoolBeforeIntern.java"
  • 可以看到常量池有个tomcat

StringNotExistInPoolBeforeIntern

javac src/main/java/com/example/javac/StringNotExistInPoolBeforeIntern.java javap -v src/main/java/com/example/javac/StringNotExistInPoolBeforeIntern.class    Last modified 2019年4月6日; size 1187 bytes   MD5 checksum 6d173f303b61b8f5826e54bb6ed5157c   Compiled from "StringNotExistInPoolBeforeIntern.java" public class com.example.javac.StringNotExistInPoolBeforeIntern   minor version: 0   major version: 56   flags: (0x0021) ACC_PUBLIC, ACC_SUPER   this_class: #11                         // com/example/javac/StringNotExistInPoolBeforeIntern   super_class: #12                        // java/lang/Object   interfaces: 0, fields: 0, methods: 2, attributes: 3 Constant pool:    #1 = Methodref          #12.#24        // java/lang/Object."<init>":()V    #2 = Class              #25            // java/lang/String    #3 = String             #26            // tom    #4 = Methodref          #2.#27         // java/lang/String."<init>":(Ljava/lang/String;)V    #5 = String             #28            // cat    #6 = InvokeDynamic      #0:#32         // #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;    #7 = Methodref          #2.#33         // java/lang/String.intern:()Ljava/lang/String;    #8 = String             #34            // tomcat    #9 = Fieldref           #35.#36        // java/lang/System.out:Ljava/io/PrintStream;   #10 = Methodref          #21.#37        // java/io/PrintStream.println:(Z)V   #11 = Class              #38            // com/example/javac/StringNotExistInPoolBeforeIntern   #12 = Class              #39            // 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              #40            // "[Ljava/lang/String;"   #21 = Class              #41            // java/io/PrintStream   #22 = Utf8               SourceFile   #23 = Utf8               StringNotExistInPoolBeforeIntern.java   #24 = NameAndType        #13:#14        // "<init>":()V   #25 = Utf8               java/lang/String   #26 = Utf8               tom   #27 = NameAndType        #13:#42        // "<init>":(Ljava/lang/String;)V   #28 = Utf8               cat   #29 = Utf8               BootstrapMethods   #30 = MethodHandle       6:#43          // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;   #31 = String             #44            // u0001u0001   #32 = NameAndType        #45:#46        // makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;   #33 = NameAndType        #47:#48        // intern:()Ljava/lang/String;   #34 = Utf8               tomcat   #35 = Class              #49            // java/lang/System   #36 = NameAndType        #50:#51        // out:Ljava/io/PrintStream;   #37 = NameAndType        #52:#53        // println:(Z)V   #38 = Utf8               com/example/javac/StringNotExistInPoolBeforeIntern   #39 = Utf8               java/lang/Object   #40 = Utf8               [Ljava/lang/String;   #41 = Utf8               java/io/PrintStream   #42 = Utf8               (Ljava/lang/String;)V   #43 = Methodref          #54.#55        // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;   #44 = Utf8               u0001u0001   #45 = Utf8               makeConcatWithConstants   #46 = Utf8               (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;   #47 = Utf8               intern   #48 = Utf8               ()Ljava/lang/String;   #49 = Utf8               java/lang/System   #50 = Utf8               out   #51 = Utf8               Ljava/io/PrintStream;   #52 = Utf8               println   #53 = Utf8               (Z)V   #54 = Class              #56            // java/lang/invoke/StringConcatFactory   #55 = NameAndType        #45:#60        // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;   #56 = Utf8               java/lang/invoke/StringConcatFactory   #57 = Class              #62            // java/lang/invoke/MethodHandles$Lookup   #58 = Utf8               Lookup   #59 = Utf8               InnerClasses   #60 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;   #61 = Class              #63            // java/lang/invoke/MethodHandles   #62 = Utf8               java/lang/invoke/MethodHandles$Lookup   #63 = Utf8               java/lang/invoke/MethodHandles {   public com.example.javac.StringNotExistInPoolBeforeIntern();     descriptor: ()V     flags: (0x0001) 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 8: 0    public static void main(java.lang.String[]);     descriptor: ([Ljava/lang/String;)V     flags: (0x0009) ACC_PUBLIC, ACC_STATIC     Code:       stack=4, locals=3, args_size=1          0: new           #2                  // class java/lang/String          3: dup          4: ldc           #3                  // String tom          6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V          9: new           #2                  // class java/lang/String         12: dup         13: ldc           #5                  // String cat         15: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V         18: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;         23: astore_1         24: aload_1         25: invokevirtual #7                  // Method java/lang/String.intern:()Ljava/lang/String;         28: pop         29: ldc           #8                  // String tomcat         31: astore_2         32: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;         35: aload_1         36: aload_2         37: if_acmpne     44         40: iconst_1         41: goto          45         44: iconst_0         45: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V         48: return       LineNumberTable:         line 11: 0         line 13: 24         line 14: 29         line 15: 32         line 16: 48       StackMapTable: number_of_entries = 2         frame_type = 255 /* full_frame */           offset_delta = 44           locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]           stack = [ class java/io/PrintStream ]         frame_type = 255 /* full_frame */           offset_delta = 0           locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]           stack = [ class java/io/PrintStream, int ] } SourceFile: "StringNotExistInPoolBeforeIntern.java" InnerClasses:   public static final #58= #57 of #61;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods:   0: #30 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;     Method arguments:       #31 u0001u0001
  • 可以看到常量池有tom、cat、tomcat

小结

  • 当调用intern方法时,如果常量池已经包含一个equals此String对象的字符串,则返回池中的字符串
  • 当调用intern方法时,如果常量池没有一个equals此String对象的字符串,将此String对象添加到池中,并返回此String对象的引用(即intern方法返回指向heap中的此String对象引用)
  • 所有literal strings及string-valued constant expressions都是interned的

doc

脚本宝典总结

以上是脚本宝典为你收集整理的聊聊java String的intern全部内容,希望文章能够帮你解决聊聊java String的intern所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。