文中相关源码:String.java
今天来说说字符串。
贯穿全文,你需要始终记住这句话,字符串是不可变类。其实前面说过的所有基本数据类型包装类都是不可变类,但是在字符串的源码中,不可变类的概念体现的更加淋漓尽致,所以,在阅读字符串源码的同时,抽丝剥茧,你会对不可变类有更深的理解。
首先来看一下什么是不可变类?有效的Java第三版第17条使不可变性最小化中对不可变类的解释:
不可变类是指其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个生命周期(生命周期)内固定不变。
为了使类成为不可变,要遵循下面五条规则:不要提供任何会修改对象状态的方法(也称为设值方法)。
引用>
保证类不会被扩展。为了防止子类化,一般做法是声明这个类成为最终的。
声明所有的域都是最终的。
声明所有的域都为私有的。这样可以防止客户端获得访问被域引用的可变对象的权限,并防止客户端直接修改这些对象。
确保对于任何可变组件的互斥访问。如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用,并且,永远不要用客户端提供的对象引用来初始化这样的域,也不要从任何访问方法(accessor)中返回该对象引用。在构造器,访问方法和readObject方法(详见第88条)中请使用保护性拷贝(防御性复制)技术(详见第50条)。根据这五条原则,来品尝一下字符串。java吧!
最后公共类字符串 java实现。可序列化的,Comparable对应原则第二点保证类不会被扩展,使用最后修饰。此外:
<李>实现了可序列化的接口,具备序列化能力李> <李>实现了可比接口,具备比较对象大小能力,根据单字符的大小比较。李> <李>实现了CharSequence进行接口,表示是一个字符序列,实现了该接口下的一些方法。李>
<强>字段强>
私人最终char[]价值;//储存字符串 私人int散列;//哈希值,默认为0 私有静态最终长serialVersionUID=-6849794470754667710 l;//序列化标识看起来的字符串是一个独立的对象,其实它是使用基本数据类型的数组char[]实现的作。为使用者,我们不需要打开弦的黑匣子,直接根据它的API使用就可以了,这正是Java的封装性的体现。但是作为开发者,我们就有必要一探究竟了。
<代码>私人最终char[]价值> 代码,对应原则中第三条和第四条,声明所有的域都是最终的,声明所有的域都为私有的。看到这里,你大概明白了一点为什么字符串不可变。因为真正用来存储字符串的字符数组是最后修饰的,是不可变的。
字符串的构造函数很多,大致可以分为以下四种:
<强>无参构造
强>公共字符串(){ this.valuehttps://www.yisu.com/zixun/=" value; }无参构造默认构建一个空字符串。鉴于字符串是不可变类,所以此构造器并没有什么意义,一般你也不会去构建一个不可变的空字符串对象。
参数是byte []
公共字符串(字节字节[]){} 公共字符串(int[],字节字节偏移量,int长度){} 公共字符串([],字符集字节字节字符集){} 公共字符串(字符串字节字节[],charsetName) {} 公共字符串(int[],字节字节偏移量,int长度、字符集字符集){} 公共字符串(int[],字节字节偏移量,int长度字符串charsetName) {}已经废弃的就不再列举了。上面这些构造函数都差不多,最后都是调用StringCoding.decode()方法将字节数组转换为字符数组,再赋值给价值[]。这里要注意一点,参数未指定编码格式的话,默认使用系统的编码格式,如果没有获取到系统编码格式,则使用iso - 8859 - 1格式。
<强>参数是char[] 强>
参数是char[]的构造函数有3个,逐个看一下:
公共字符串(char[]价值){ 这一点。值=https://www.yisu.com/zixun/Arrays.copyOf(价值,value.length); }走进JDK之不可变类字符串