为什么String被设计为不可变类
-
保证String对象的安全性。假设String对象时可变的,那么String对象将可能被恶意修改
-
保证
hash
属性值不会频繁变更,确保了唯一性,使得类似HashMap
容器才能实现响应的key-value
缓存功能 -
可以实现字符串常量池。在Java中,通常两个创建字符串对象的方式,
-
通过字符串常量的方式创建
String str = "abc"
-
字符串变量通过
new
形式的创建String str = new String("abc")
-
new String("abc")
方式创建String对象
通过new String("abc")
方式创建String对象时,
-
在编译类文件时, “abc”常量字符串将会放入到常量结构中
-
在类加载时,
"abc"
将会在常量池中创建 -
在调用
new
时,JVM命令将会调用String的构造函数,同时引用常量池中的"abc"
字符串,在堆内存中创建一个String
对象
String.intern
方法使用原理
在字符串常量中,默认会将对象放入常量池;
在字符串变量中,对象是会创建在堆内存中,同时也会在常量池中创建一个字符串对象,String对象中的char数据
会引用常量池中的char数据
, 并返回对内存对象引用
如果调用intern
方法,会去查看字符串常量池中是否有等于该对象的字符串的引用,如果没有,在JDK1.6
版本中会复制堆中的字符串到常量池中,并返回该字符串引用,堆内存中原有的字符串由于没有引用指向它,将会通过垃圾回收器回收。
在JDK1.7
版本以后,由于常量池已经合并到堆中,所以不会再复制具体字符串了,只是会把首次遇到的字符串引用添加到常量池中;如果有,就返回常量池中的字符串引用。
使用坑点
使用intern
方法需要注意的一点是,一定要结合实际场景,因为常量池的实现是类似于一个HashTable
的实现方式,HashTable
存储的数据越大,遍历的时间复杂度就会增加。如果数据过大,会增加整个字符串常量吃的负担。
文章评论