java字符串的两种创建方式以及与字符串常量池的关系

关于java字符串创建与常量池的关系,之前能分清的一些点现在有些记忆模糊了,做一个学习笔记。

String字符串的两种创建方式

1.new关键字创建

String s1 = new String("aa");

这种方式有可能会创建两个对象。

首先去字符串常量池中找有没有"aa",发现没有,就会在字符串常量池中创建"aa"。

然后在堆中创建一个新对象"aa",并且返回引用。s1指向的就是堆中的这个对象。

2.字面量创建

String s2 = "bb";

用字面量"bb"直接对s2初始化。
这种方式会先到字符串常量池中去找有没有"bb",如果有直接返回"bb"的引用;如果没有就在字符串常量池中创建这个对象,然后返回它的引用。

intern()方法

intern
public String intern()

Returns a canonical representation for the string object. 
A pool of strings, initially empty, is maintained privately by theclass String. 

When the intern method is invoked, if the pool already contains astring equal to this String object as determined bythe equals(Object) method, then the string from the pool isreturned. 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 trueif and only if s.equals(t) is true. 

All literal strings and string-valued constant expressions areinterned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.
Returns:a string that has the same contents as this string, but isguaranteed to be from a pool of unique strings.

当调用intern()方法的时候,如果字符串常量池已经有这个字符串了,就直接返回字符串常量池中的字符串;否则把此对象添加到字符串常量池,并且返回它的引用。(注:1.7之后版本

对两种方式创建的字符串对象都分别调用一下intern()方法:

		String s1 = new String("aa");
		String s2 = "bb";	
		String s3 = "aa";
		
		System.out.println(s1.intern()==s1);//false	
		System.out.println(s2.intern()==s2);//true
		System.out.println(s1.intern()==s3);//true

第一个输出fasle。s1指向堆,s1.intern()指向字符串常量池。
第二个输出true。s2指向字符串常量池,s2.intern()也指向字符串常量池。
第三个输出true。s3指向字符串常量池,s1.intern()指向字符串常量池。

通过上述例子可以稍稍明白字符串创建与字符串常量池的关系。那么再看一个特殊例子:

		String s4 = new String("a") + new String("b");
		
		System.out.println(s4.intern()==s4);//true

同样是用new关键字创建,怎么s4.intern()==s4的结果与s1.intern()==s1的结果不一样?来看s4的初始化过程。

首先去字符串常量池判断是否有"a"和"b",发现没有,于是在字符串常量池中创建"a"和"b"。

然后轮到new关键字,在堆中创建了"a"和"b"两个对象之后,会把它们相加之后的对象"ab"给到s4。

此时s4指向堆中的"ab",而字符串常量池中是没有"ab"这个对象的。

所以对s4调用intern()方法时,去字符串常量池中找不到"ab",就会把堆中的"ab"放到字符串常量池中去,再返回它的引用。那么s4.intern()==s4当然就会返回true了。

关于字符串常量池的存储位置到底在哪里,说法太多了,有一位博主做了详细的测试,我认为是可信的:java8以后字符串常量池的位置,以及元空间的探秘,使用VisualVM进行实战验证

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值