Java-String.intern方法

该博客围绕Java帮助文档展开,重点介绍了String类的intern()方法。此方法返回字符串对象的规范表示,涉及字符串池的操作。当调用该方法时,会根据字符串池的情况返回相应字符串。还提到所有文字字符串和字符串值常量表达式都是实体,最后给出参考文档链接。

java帮助文档

String java.lang.String.intern()
Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() = = t.intern() is true if and only if s.equals(t) is 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.
返回字符串对象的规范表示。最初为空的字符串池由String类私有维护。调用实习方法时,如果池已经包含等于此字符串对象的字符串(由equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。因此,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern()== t.intern()才为真。所有文字字符串和字符串值常量表达式都是实体。字符串文字在Java语言规范返回的
§3.10.5中定义:与此字符串具有相同内容的字符串,但保证来自唯一字符串池。
上代码:

String s1 = new String("aaa");
String s2 = "aaa";
System.out.println(s1 == s2);    // false

s1 = new String("bbb").intern();
s2 = "bbb";
System.out.println(s1 == s2);    // true

s1 = "ccc";
s2 = "ccc";
System.out.println(s1 == s2);    // true

s1 = new String("ddd").intern();
s2 = new String("ddd").intern();
System.out.println(s1 == s2);    // true

s1 = "ab" + "cd";
s2 = "abcd";    
System.out.println(s1 == s2);    // true

String temp = "hh";
s1 = "a" + temp;
// 如果调用s1.intern 则最终返回true
s2 = "ahh";
System.out.println(s1 == s2);    // false

temp = "hh".intern();
s1 = "a" + temp;
s2 = "ahh";
System.out.println(s1 == s2);    // false

temp = "hh".intern();
s1 = ("a" + temp).intern();
s2 = "ahh";
System.out.println(s1 == s2);    // true

s1 = new String("1");    // 同时会生成堆中的对象 以及常量池中1的对象,但是此时s1是指向堆中的对象的
s1.intern();            // 常量池中的已经存在
s2 = "1";
System.out.println(s1 == s2);    // false

String s3 = new String("1") + new String("1");    // 此时生成了四个对象 常量池中的"1" + 2个堆中
//的"1" + s3指向的堆中的对象(注此时常量池不会生成"11")
s3.intern();    // jdk1.7之后,常量池不仅仅可以存储对象,还可以存储对象的引用,会直接将s3的地址存储在常量池
String s4 = "11";    // jdk1.7之后,常量池中的地址其实就是s3的地址
System.out.println(s3 == s4); // jdk1.7之前false, jdk1.7之后true

s3 = new String("2") + new String("2");
s4 = "22";        // 常量池中不存在22,所以会新开辟一个存储22对象的常量池地址
s3.intern();    // 常量池22的地址和s3的地址不同
System.out.println(s3 == s4); // false

// 对于什么时候会在常量池存储字符串对象,我想我们可以基本得出结论: 
// 1. 显示调用String的intern方法的时候; 2. 直接声明字符串字面常量的时候,例如: String a = "aaa";
// 3. 字符串直接常量相加的时候,例如: String c = "aa" + "bb";  
//其中的aa/bb只要有任何一个不是字符串字面常量形式,都不会在常量池生成"aabb". 且此时jvm做了优化,
//不会同时生成"aa"和"bb"在字符串常量池中
Integer[] DB_DATA = new Integer[10];
Random random = new Random(10 * 10000);
for (int i = 0; i < DB_DATA.length; i++) {
    DB_DATA[i] = random.nextInt();
}
long t = System.currentTimeMillis();
for (int i = 0; i < MAX; i++) {
    arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));                // --- 每次都要new一个对象
    // arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();    --- 其实虽然这么多字符串,但是类型最多为10个,大部分重复的字符串,大大减少内存
}

System.out.println((System.currentTimeMillis() - t) + "ms");
System.gc();

参考文档:https://www.cnblogs.com/Kidezyq/p/8040338.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值