JDK8源码研究(一):java.lang.String
首先看官方的注释:
大致的意思是,这个String类代表了字符串,所有的JAVA程序设计中的字符串的字面常量,例如"abc",都是这个类的实例。String类是常量,他的值在创建以后就无法更改,String buffers支持可变的字符,因为String是不可变的所以他们可以用于共享。例如:String str="abc"和 char data[] = {'a','b','c'}; String str=new String(data);这两个是相等的。该类包括了单个字符序列的审查
比较字符串、搜索字符串、提取子字符串、和拷贝字符串并转换成大写或者小写。大小写对应是基于通过Character类指定的Unicode标准版本。
然后可以看到String类实现了三个接口,分别是Serializable、Compareble、CharSequence。
Serializable是序列化对象都要实现的标准接口,Compareble接口用于比较String的大小,可用于集合类的排序等,CharSequence定义了字符串的各类操作方法。
String类的两个比较重要的私有属性,一个char基本类型的数组,一个维护该类实例的hash值缓存。
来看看String类的几个关键的构造方法:
通过一个char数组和一个偏移值和一个长度三个参数来构建String实例。我们平时常用的通过char数组的构造方法最终就是调用了这个构造方法。其中offset就是0,count就是value[].length。可以看到这个构造方法前面大部分都是在检测offset和count参数的值是否合法,如果不合法就抛出一个StringIndexOutOfBoundsException的运行时异常。最终通过Arrays这个工具类的copyOfRange拷贝数据的方法将value[]数据的值拷贝到String类的私有属性value中去。
另一个比较常用的构造方法是通过字节流(一个字节数据)来创建String实例。先检查了参数是否有数组越界,其字节数组到字符数组的转换委托给了StringCoding这个类来操作。
可以看到,StringCoding回去查找用户系统默认编码集名称,如果找到了,直接进行编码,如果没找到,就用ISO-8859-1编码集进行编码,并且捕获一个UnsupportedEncodingException异常,如果ISO-8859-1这个JDK默认的编码集不存在被认为安装发生了一个很严重的问题,JDK会直接执行System.exit(1);直接非正常退出。
还有两个通过StringBuilder和StringBuffer类的构造方法,差别不大,因为StringBuffer是线程不安全的,所以再拷贝其字符数组的时候先把他锁住。而这两个类就是前面提到的可变的字符串类。
常用的几个方法,都是比较简单的逻辑,其实就是封装了对char数据的操作,加上一些检查。
String类重写了equals方法,其比较是对char数组中的字符逐一进行比较,如果全部相同就返回true。
String类还提供了一个和其他CharSequence实现类进行比较的方法,其具体比较的算法和上面一样,只是获取CharSequence实现类的字符使用了charAt(int index)这个方法,并且对StringBuffer采用了有锁的比较。
该方法就是Compareble定义的方法,具体的逻辑就是比较的两个字符串同一索引值上的字符如果对应的值大小不同就相减并返回。
重写了hashCode的方法,具体算法是time33算法。
裁剪字符创的方法,可以看到先进行参数的检查,然后判断如果裁剪的范围是自己本身的范围,就把自己返回,否则就创建一个新的String实例。