标签:设计 serial 改变 class vat 创建 自动 地址 char
1. String中什么是不可变的
2 .怎么实现的不可变
3.为什么要设计成不可变的
下面就来一起看一下这几个问题吧
一。String对象有两种创建方式,一种就是直接通过new ,另一种一种就是直接赋值
String s1 = new String("abc"); String s2 = "abc";
一种是在堆中创建对象,一种实在常量池中创建对象(jdk1.7以后也放在堆中),然后由栈中的引用对象指向堆中的地址,
String s1 = s1+"abc";输出的s1是变成了"abcbc",但不过只是s1指向的堆内存地址发生了变化,之前的那个"abc"对象还是存在的,只不过没有人使用它了,一段时间后就会被GC自动回收掉;
其实只要明白栈中存储对象的引用,堆中存储对象实例,就能想清楚,堆内存中的对象是不会由于引用指向的改变而变化的,要想改变只能从内部着手,然而String并没有提供”setter“方法,
所以String对象的不可变,不管你是说长度不可变也好,内容不可变也好,总之就是对象一旦创建就是不可变,由于没有"setter"方法
不知到有没有跟笔者刚开始学的时候一样,总是弄不清楚s1.replace("a","f");要不要重新创建一个引用对象来保存这个新的字符串,现在可以肯定的告诉你“需要”,因为String对象不可变,猜也能猜到内部一定是创建一个新的对象来存储,不信的可以自己翻一下源码。
二。然后就来看一下String类是怎么实现的不可变,简单的理解可以认为没有”setter“方法供已操作
下面看一下String的源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
...
}
其实这三点就能够确保String对象的不可变性了。
三。那么为什么要对String有这样的设计呢?
1。字符串常量池的需要,常量池是为了减少字符串的创建,当常量池中有此字符串时,即 String str1 = "ABC", String str2 = "ABC",str1和str2会指向同一个地址,如果str1发生改变,会影响str2的值
2。安全考虑 String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。
3。hacode用到 String类被用这hashcode计算,String不可变能够缓存key的hash值从而不用每次都需要重新计算,减少性能开销。
标签:设计 serial 改变 class vat 创建 自动 地址 char
原文地址:https://www.cnblogs.com/zjgp/p/11638539.html