您的位置:首页 > 编程语言 > Java开发

Java之String

2016-07-27 21:06 387 查看
要理解清楚java String,首选需要区分String Literals和String类

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

一个String Literal 由0个到多个字符组成,并且包在双引号中间。

一个String Literal 总是String 类型的。

一个String Literal 是String类的实例的引用。

String Literal总是指向同一个String实例,这是因为String Literal是常量表达式,并且被”interned”了,这样就可以共享String实例提高效率了。

二. String类

String实例代表了Unicode编码的字符序列

String Literal 是String类实例的引用

三. 连接操作

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对象。

四. 分配与回收

String Listeral指向的String实例是分配在堆的特殊区域中的。

String Listeral指向的String实例是不会被回收的。我们可以不停的调用String.intern,然后就会报内存溢出的异常。

对象个数,经常有面试的问,下面的代码分别了几个对象。有了上面的知识,就比较轻松的知道应该是两个对象。其实分别了几个对象,只要写个小李子,用==判断一下就可以了。

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  string Java String池