Java之String

要理解清楚java String,首选需要区分String Literals和String类

一. 字符串字面值(String Literals)

  1. 一个String Literal 由0个到多个字符组成,并且包在双引号中间。
  2. 一个String Literal 总是String 类型的。
  3. 一个String Literal 是String类的实例的引用。
  4. String Literal总是指向同一个String实例,这是因为String Literal是常量表达式,并且被”interned”了,这样就可以共享String实例提高效率了。

二. String类

  1. String实例代表了Unicode编码的字符序列
  2. String Literal 是String类实例的引用

三. 连接操作

  1. String的连接(+)将产生一个新的String实例,除非这个表达式是常量表达式。

四. 实例

//两个包
package other;
       public class Other { public static String hello = "Hello"; }

package testPackage;
 class Test {
       public static void main(String[] args) {
               String hello = "Hello", lo = "lo";
               System.out.print((hello == "Hello") + " ");
               System.out.print((Other.hello == hello) + " ");
               System.out.print((other.Other.hello == hello) + " ");
               System.out.print((hello == ("Hel"+"lo")) + " ");
               System.out.print((hello == ("Hel"+lo)) + " ");
               System.out.println(hello == ("Hel"+lo).intern());
} }
class Other { static String hello = "Hello"; }

执行结果

true true true true false true

结论
1. Listeral Strings在同一个Class同一个package下,是引用了相同的String对象。
2. Listeral Strings在同一个package不同的Class下,是引用了相同的String对象。
3. Listeral Strings在不同的package不同的Class下,也是引用了相同的String对象。
4. String的常量表达式计算是在编译期间发生的,并且作为Listeral对待。
5. Strings的连接计算是在运行时发生的,会创造 一个新的String对象,因此是不同的。
6. intern计算得到的结果和之前存在的Listeral是同一个String对象。

四. 分配与回收

  1. String Listeral指向的String实例是分配在堆的特殊区域中的。
  2. String Listeral指向的String实例是不会被回收的。我们可以不停的调用String.intern,然后就会报内存溢出的异常。
  3. 对象个数,经常有面试的问,下面的代码分别了几个对象。有了上面的知识,就比较轻松的知道应该是两个对象。其实分别了几个对象,只要写个小李子,用==判断一下就可以了。
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");

六. intern的使用

一般情况下,我们不会用到intern方法。但是,有时intern确实可以节省大量的内存和CPU。比如我们的应用需要保存住在Greece的所有人的详细住址信息,我们用下面的结构来保存。

class Address{
        private String city;
        private String street;
        private String streetNumber;
        private String zipCode;
}

假如Athens市中住了400万人,那city就需要保存400万个Athens值。如果我们使用了city.intern()的话,就会节省大量的空间。
但是使用时必须小心,在java7之前,String pool是保存在堆中的特殊区域,称之为”PermGen”,PermGen是固定大小的,只能保存一定数量的String Listeral,所以只有非常熟练的人才去使用intern。 但是从java7开始,这个区域将会保存在普通的堆区,和其它的对象一样。是已hashmap的形式存在的,并且你可以用-XX:StringTableSize来调整大小。

七. String Pool大小

要注意的是,String的String Pool是一个固定大小的Hashtable,默认值大小长度是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。
在 jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。在jdk7中,StringTable的长度可以通过一个参数指定:
-XX:StringTableSize=99991
具体的intern详解,请查看深入解析String#intern

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值