2019独角兽企业重金招聘Python工程师标准>>>
jdk1.8中String的intern方法简单介绍
先来看三段代码:
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对不对?
好下面来简单讲解一下:
首先贴一段jdk源码的注释,记住永远以源码以及源码注释作为最重要的参考, 其他的博客包括这篇都包含了作者的强烈的主观意识在里面可能会误导你。
/**
* Returns a canonical representation for the string object.
*
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
*
* 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.
*
* 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}.
*
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* The Java™ Language Specification.
*
* @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();
我英文不是很好,随便翻一下。 大意是说如果调用该方法,如果常量池中包含了一个和当前对象相等的字符串则返回常量池中的字符串, 否则把改字符串放到常量池中,并返回字符串的引用.
下面来简单看下第一段代码: 我们把
String s1 = new String("abc");
拆成两部分
//此时常量池中没有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 true
第二段代码其实和第一段类似就不解释了
直接看第三段吧
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
怎么样很好理解吧?
如果对你有帮助欢迎留个言或者点个赞,说的不对的地方也欢迎指正。