String类可谓是java编程中出现频率最高的类了。今天来看看它的实现和一些常用方法。
1. 值表示
String是字符串类,字符串本质就是一系列字符的顺序排列。它有两个关键点:字符本身和他们的排列顺序。用来表示一组元素的有序集合,我们首先想到的数据结构就是数组。所以String就是使用一个名为value的字符数组来存储字符串的值的。看源码:
可以看到 value[] 使用 final 修饰符,说明 value 值不可变。而我曾经从面试经验中得知“String对象是不可变的”,所以当我从源码中第一眼看到这个 final 时,略微激动地以为它就是字符串对象不变性的原因。但仔细想想却并不是这么回事,因为 value[] 是一个数组类型,数组类型本质上也是引用类型,所以使用 final 修饰 value 只是说明 value 不能指向新的数组,但是却是可以改变 value 数组中元素的值的,而改变元素的值,也就改变了String对象。所以,value 的final修饰符并不是String对象不变性的原因,而是String所有更新操作方法(concat、replace、toLowerCase等)都会new一个新的String对象返回,这才是保证String对象不变性的原因。后文中会提到一些方法。
2. compareTo比较
String 比较是依次按位比较字符的编码大小,若当前索引的字符更大则代表字符串更大,这种比较直至某一个较短的字符串结尾,那么认为较长的字符串更大。
public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
3. hashCode 方法
String 哈希值计算方式是按位将累加结果乘31而得到的,并且使用属性 hash 保存其值,因为String是不变的,所以没有必要重复计算。
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
4. concat方法
String 的 concat 方法用于将参数字符串连接到当前字符串尾部并生成新的字符串对象。
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
5. replace(char oldChar, char newChar)方法
将原字符串中所有 oldChar 字符替换成 newChar 字符,并生成新的字符串对象。但是如果 oldChar=newChar 或者原字符串中不包含 oldChar 字符时,不会生成新的字符串对象,而是直接返回原字符串。