String s1 = new String("abc"); s1.intern(); String s2 = "abc"; //s1 == s2 ? false System.out.println(String.format("s1 == s2 ? %s", s1 == s2));
String s3 = new String("def") + new String(""); s3.intern(); String s4 = "def"; //s3 == s4 ? false System.out.println(String.format("s3 == s4 ? %s", s3 == s4));
String s5 = new String("hi") + new String("j"); s5.intern(); String s6 = "hij"; //s5 == s6 ? true System.out.println(String.format("s5 == s6 ? %s", s5 == s6));
s1 == s2 ? false s3 == s4 ? false s5 == s6 ? true
驚不驚喜,意不意外? 按道理應該都是true或者都是false對不對?java
首先貼一段jdk源碼的註釋,記住永遠以源碼以及源碼註釋做爲最重要的參考, 其餘的博客包括這篇都包含了做者的強烈的主觀意識在裏面可能會誤導你。express
/** * 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. */ public native String intern();
我英文不是很好,隨便翻一下。 大意是說若是調用該方法,若是常量池中包含了一個和當前對象相等的字符串則返回常量池中的字符串, 不然把改字符串放到常量池中,並返回字符串的引用.ide
下面來簡單看下第一段代碼: 咱們把this
String s1 = new String("abc");
拆成兩部分code
//此時常量池中沒有abc,將abc放到常量池中 String s = "abc"; //對象s引用地址的hashCode long sRefHashCode = System.identityHashCode(s); System.out.println(String.format("s identityHashCode :[%s]", sRefHashCode)); String s1 = new String(s); //對象s1引用地址的hashCode long s1RefHashCode = System.identityHashCode(s1); System.out.println(String.format("s1 identityHashCode :[%s]", s1RefHashCode)); //此時常量池中有abc,返回常量池中abc即對象s String s1Intern = s1.intern(); long s1InternRefHashCode = System.identityHashCode(s1Intern); System.out.println(String.format("s1Intern identityHashCode :[%s]", s1InternRefHashCode)); //此時常量池中有abc,返回abc,即對象s String s2 = "abc"; //對象s2引用地址的hashCode long s2RefHashCode = System.identityHashCode(s2); System.out.println(String.format("s2 identityHashCode :[%s]", s2RefHashCode)); //false System.out.println(String.format("s1RefHashCode == s1InternRefHashCode ? %s", s1RefHashCode == s1InternRefHashCode)); //false System.out.println(String.format("s1RefHashCode == s2RefHashCode ? %s", s1RefHashCode == s2RefHashCode)); //true System.out.println(String.format("s1InternRefHashCode == s2RefHashCode ? %s", s1InternRefHashCode == s2RefHashCode)); //false System.out.println(String.format("s1 == s1Intern ? %s", s1 == s1Intern)); //false System.out.println(String.format("s1 == s2 ? %s", s1 == s2)); //true System.out.println(String.format("s1Intern == s2 ? %s", s1Intern == s2));
把這段代碼執行一遍,會發現
因爲在建立s1以前,常量池中已經有abc了,
因此執行s1.intern()時直接返回了常量池中的abc,
s2也是從常量池中獲取的,而s1則是從新建立的對象
因此
s1 == s1.intern() false
s1 == s2 false
s1.intern() == s2 trueorm
第二段代碼其實和第一段相似就不解釋了對象
直接看第三段吧ci
String s1 = new String("hi") + new String("j"); long s1RefHashCode = System.identityHashCode(s1); System.out.println(String.format("s1 identityHashCode :[%s]", s1RefHashCode)); //此時常量池中有沒有hij,將s1放入到常量池並返回s1的引用 String s1Intern = s1.intern(); long s1InternRefHashCode = System.identityHashCode(s1Intern); System.out.println(String.format("s1Intern identityHashCode :[%s]", s1InternRefHashCode)); //此時常量池中有hij,返回hij,即對象s1 String s2 = "hij"; long s2RefHashCode = System.identityHashCode(s2); System.out.println(String.format("s2 identityHashCode :[%s]", s2RefHashCode)); //true System.out.println(String.format("s1RefHashCode == s1InternRefHashCode ? %s", s1RefHashCode == s1InternRefHashCode)); //true System.out.println(String.format("s1RefHashCode == s2RefHashCode ? %s", s1RefHashCode == s2RefHashCode)); //true System.out.println(String.format("s1InternRefHashCode == s2RefHashCode ? %s", s1InternRefHashCode == s2RefHashCode)); //true System.out.println(String.format("s1 == s1Intern ? %s", s1 == s1Intern)); //true System.out.println(String.format("s1 == s2 ? %s", s1 == s2)); //true System.out.println(String.format("s1Intern == s2 ? %s", s1Intern == s2));
把這段代碼執行一遍,會發現
因爲在建立s1以前,常量池中沒有hij,
因此執行s1.intern()時會將s1放入到常量池中,並返回s1的引用,
s2也是從常量池中獲取的, 因此
s1 == s1.intern() true s1 == s2 true
s1.intern() == s2 true字符串
怎麼樣很好理解吧?
若是對你有幫助歡迎留個言或者點個贊,說的不對的地方也歡迎指正。源碼