序
string.intern()
java.base/java/lang/string.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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
1
2
3
4
5
6
7
8
9
10
|
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
1
2
3
4
5
6
7
8
9
10
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
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的
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。
原文鏈接:https://segmentfault.com/a/1190000018775484