java字符串常量池

java的String是不可变类。为了提高效率,java为String类提供了String池。

1. 当我们使用形如String s = "abc"的代码为字符串赋值时,JVM首先会检查字符串常量池中是否有"abc"这个字符串,如果有就直接将其地址赋给s;若没有,则在Stirng池中创建一个字符串对象“abc”,再将其地址赋给s。

例如:
public static void main(String[] args) {
        String s1="hello";
        String s2="hello";
        String s3="he"+"llo";
        System.out.println(s1==s2);
        System.out.println(s2==s3);
}

上述代码中,执行String s1 = "hello"时JVM在String池中创建了“hello”对象;当执行到String s2="hello"时,因为此时String池中已经有了“hello”,编译器就直接将“hello”的地址赋给s2。因此s1、s2指向了同一个对象,所以输出为true。S3也是同样道理。


是否入池要看情况而定,等号右边如果是常量则入池,非常量则不入池
String s3 = "a" + "b"; //"a"是常量,"b"是常量,常量+常量=常量,所以会入池.
String s4 = s1 + "b";   //s1是变量,"b"是常量,变量+常量!=常量,所以不会入池.


2. 当使用String s=new String("");这种形式赋值时,实际上产生了两个对象。
例如:String s=new String("abc"),此时先是在String常量池中产生了一个“abc”对象,然后new String()又在堆中分配了内存空间,将常量区中的“abc"复制一份给了堆中的String对象。因此这段代码产生了两个对象,一个在常量区、一个在堆区。
public static void main(String[] args) {
        String s1="hello";
        String s2=new String("hello");
        System.out.println(s1==s2);
}

这里s1指向的是常量区中的”hello“,s2指向的是堆中的”hello“,因此输出为false。


3. java.lang.String的intern()方法 
一个初始时为空的字符串池,它由类 String 私有地维护。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 
它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

String str1 = "a";
String str2 = "bc";
String str3 = "a" + "bc";
String str4 = str1 + str2;

System.out.println(str3 == str4);  // false
str4 = (str1 + str2).intern();
System.out.println(str3 == str4);  //true 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值