String中的intern()方法分析(图文并茂容易理解)

String类中的intern()方法。

/**
 * 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.
 */
public native String intern();

当一个字符串调用intern()方法时会经历 如下过程。

String s1 = “jvm”(我们直接给String变量赋值时会在常量池中分配一块空间)

String s2 = new String(“jvm”) (我们通过new的方式创建字符串的时候,我们在堆中分配空间)

 

1.关于 + 运算符对字符串的拼接

String s1 = “a”;
String s2 = “b”;
String s3 = “ab”;
String s4 = “a” + “b”
String s5 = s1 + s2;

 

对于s4由于常量池中已经存在”ab”所以s4直接指向该地址空间

对于s5由于s1和s2不是final修饰的所以会创建一个新的String对象,此时空间在堆中分配

扫描二维码关注公众号,回复: 12535364 查看本文章

 

//我们将s1和s2使用final修饰
final String s1 = “a”;
final String s2 = “b”;
String s3 = “ab”;
String s4 = “a” + “b”
String s5 = s1 + s2;

 

此时s5也指向了常量池中的字符串对象了,在编译期间我们由于s1和s2是常量并且是final修饰的即不可变的常量,当我们到s5时会直接将s1和s2替换成”a” + “b”

 

String s1 = “a” + new String(“b”);

 

对于s1我们现在常量池中创建一个字符串a,然后再堆中new String(“b”),最后拼接两个字符串时,我们会新创建一个对象new String(“ab”)

 

String s1 = new String(“a” + “b”);

 

对于字符串s1我们先进行”a” + “b”,编译时会进行优化”a” + “b”直接又”ab”替换,然后我们再堆中创建一个新的对象。

 

2.关于intern()方法

String s1 = “ab”;
String s2 = new String(“ab”);
s2.intern();

 

在s2.intern()时,会先去常量池中查看是否有”ab”这个字符串,发现有直接返回常量池中”ab”的地址。

 

String s1 = new String(“ab”);
s1.intern();

在s1调用intern()方法以后,发现常量池中不存在”ab”这个常量,在jdk1.7之前我们会直接拷贝一份”ab”放在常量池中,而在jdk1.7后我们不会直接拷贝值而是复制一份s1引用地址在常量池中,最后直接返回常量池中的地址。

 

 

最后

分析几道题巩固所学知识(题目来源菜鸟教程)

String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = str1 + str2;
String str5 = new String("ab");
 
System.out.println(str5.equals(str3));     //true
System.out.println(str5 == str3);           //false
System.out.println(str5.intern() == str3); //true
System.out.println(str5.intern() == str4); //false

第一个为true,String类覆写了equals方法两个字符串引用的值相等时,就返回true

第二个为false,str3指向常量池的地址,str5指向堆中的地址

第三个为true,str5.intern()时会先去常量池中查看是否有”ab”字符串,发现有(之前str3赋值时加入到常量池的值),所有str5.intern()与str3都是指向常量池中相同的位置

第四个为false,str4会在堆创建一个新的对象

 

String a = new String("ab");
String b = new String("ab");
String c = "ab";
String d = "a" + "b";
String e = "b";
String f = "a" + e;

System.out.println(b.intern() == a); //false
System.out.println(b.intern() == c); //true
System.out.println(b.intern() == d); //true
System.out.println(b.intern() == f); //false
System.out.println(b.intern() == a.intern()); //true

如下图解

猜你喜欢

转载自blog.csdn.net/weixin_41237676/article/details/108267130