Java之String
2016-07-27 21:06
387 查看
要理解清楚java String,首选需要区分String Literals和String类
一个String Literal 总是String 类型的。
一个String Literal 是String类的实例的引用。
String Literal总是指向同一个String实例,这是因为String Literal是常量表达式,并且被”interned”了,这样就可以共享String实例提高效率了。
String Literal 是String类实例的引用
执行结果
结论
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.intern,然后就会报内存溢出的异常。
对象个数,经常有面试的问,下面的代码分别了几个对象。有了上面的知识,就比较轻松的知道应该是两个对象。其实分别了几个对象,只要写个小李子,用==判断一下就可以了。
假如Athens市中住了400万人,那city就需要保存400万个Athens值。如果我们使用了city.intern()的话,就会节省大量的空间。
但是使用时必须小心,在java7之前,String pool是保存在堆中的特殊区域,称之为”PermGen”,PermGen是固定大小的,只能保存一定数量的String Listeral,所以只有非常熟练的人才去使用intern。 但是从java7开始,这个区域将会保存在普通的堆区,和其它的对象一样。是已hashmap的形式存在的,并且你可以用-XX:StringTableSize来调整大小。
在 jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。在jdk7中,StringTable的长度可以通过一个参数指定:
-XX:StringTableSize=99991
具体的intern详解,请查看深入解析String#intern
一. 字符串字面值(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
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序