public class StringIntern {
public static void main(String[] args) {
//第一种情况:此时字符串常量池中还没有he这个字符串
String str = "he".intern();//he一开始不存在字符串常量池中,调用intern方法在常量池中创建一个,并返回该字符串的引用
System.out.println(str.hashCode());//3325
System.out.println(str.intern().hashCode());//3325
System.out.println(System.identityHashCode(str));//621009875:获取str的系统内存地址
System.out.println(System.identityHashCode(str.intern()));//621009875
System.out.println(str == str.intern());//true
System.out.println("=======用intern比较堆中与字符串常量池中的字符串是否相等=======");
String str2 = new String("he");
//使用 new 关键字创建的字符串对象会先从字符串常量池中找,如果没找到就在字符串常量池中创建一个
//然后再在堆中创建字符串对象;如果找到了,就直接在堆中创建字符串对象。
//此时字符串常量池中已经有了he这个字符串,所以会直接在堆中创建一个新的he对象,
//此时字符串常量池中的he和堆中的he的引用地址不一样
System.out.println(str2.hashCode());//3325
System.out.println(str.hashCode());//3325
System.out.println(System.identityHashCode(str2));//1265094477
System.out.println(System.identityHashCode(str));//621009875
System.out.println(str2 == str.intern());//false
/*
* hashCode得出的哈希值与identityHashCode得出的哈希值不一样,说明hashCode方法在得到真实
* 的地址后又做了某些操作。
* /
/**
* 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.
*
* 当调用intern方法时,如果字符串常量池中已经包含了一个等于此string对象的字符串(由equals方法确定)
* 那么将返回池中的字符串。否则,将该String对象将添加到池中,并返回对此对象的引用。
*
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
* 与此字符串具有相同内容的字符串,但保证来自唯一字符串池
*/
/**
* 第一种情况:字符串常量池和堆中都不存在该字符串,调用str.intern()方法时,
* 会在字符串常量池中创建该字符串并返回代表该字符串的引用
* 第二种情况:字符串常量池中不存在,堆中存在,会直接将堆中字符串对象的引用
* 地址存放在字符串常量池中,
* 第三种情况:字符串常量池中存在,会直接返回该字符串的引用地址。
*
* Java 7(不包括7)之前:
* 执行 String.intern()方法的时候,不管对象在堆中是否已经创建,字符串常量
* 池中如果没有的话仍然会创建一个内容完全相同的新对象;即 =>即使堆中已经存在该字符串对象了
* 如果字符串常量池中不存在依然会在字符串常量池中创建一个完全相同的字符串对象,并返回该字符串的引用
* 但是在Java7之后,由于字符串常量池放在了堆中,执行String.intern()方法的时候,如果对象
* 在堆中已经创建了,字符串常量池中就不再创建新的对象,而是直接保存堆中对象的引用,即字符串常量池中
* 存放的是堆中字符串对象的引用地址而不是字符串常量池中新创建的字符串对象
*
* */
}
}
借鉴:
intern() 方法 - 知乎 (zhihu.com)