关于java String中intern的深入讲解
程序员文章站
2024-02-22 19:02:12
序
本文主要研究一下java string的intern
string.intern()
java.base/java/lang/string.java...
序
本文主要研究一下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™ 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 // \u0001\u0001 #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 \u0001\u0001 #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 \u0001\u0001
可以看到常量池有tom、cat、tomcat
小结
当调用intern方法时,如果常量池已经包含一个equals此string对象的字符串,则返回池中的字符串
当调用intern方法时,如果常量池没有一个equals此string对象的字符串,将此string对象添加到池中,并返回此string对象的引用(即intern方法返回指向heap中的此string对象引用)
所有literal strings及string-valued constant expressions都是interned的
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
上一篇: Rt-Thread学习笔记-----消息队列(四)
下一篇: mybatis查询语句揭秘之参数解析