String类源码分析 -- by maxwell
今天把String类的源码看了一遍,该类大概2000多行代码,注释就有1000多行。这个类主要都是对char[]的操作。
我大概注释了60%左右的方法,重要的方法做了分析注释,对这些方法也算有了比较深刻的认识。
String的底层是使用数组实现的。
/** The value is used for character storage. */
private final char value[];
构造方法
//无参构造
public String() {
this.value = new char[0];
}
//将char[]转化为字符串
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
//分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
//offset 参数是子数组第一个字符的索引,count 参数指定子数组的长度。
//实际上是调用了Arrays.copyOfRange()方法实现的。
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) { //注意这个边界检查
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
//将byte[]转化为字符串
public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length); //检查边界,这个方法里面就是使用if()语句判断边界是否合法
this.value = StringCoding.decode(charsetName, bytes, offset, length);
}
//上面调用的checkBounds()方法,该方法是private的,用于检测边界值
private static void checkBounds(byte[] bytes, int offset, int length) {
if (length < 0)
throw new StringIndexOutOfBoundsException(length);
if (offset < 0)
throw new StringIndexOutOfBoundsException(offset);
if (offset > bytes.length - length)
throw new StringIndexOutOfBoundsException(offset + length);
}
//将StringBuffer类型数据转化为字符串
//底层实现是使用的Arrays.copyOf()方法
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
//将StringBuilderr类型数据转化为字符串,实现和StringBuffer的是一样的
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
常用方法
//获取字符串长度
//实际上就是返回了char[]的长度
public int length() {
return value.length;
}
//判断字符串是否为空串
//实际上就是判断数组的长度是否为0
public boolean isEmpty() {
return value.length == 0;
}
//取指定index位置上的char值
//实际上是通过index返回char[]数组的内容
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
//从dstBegin开始位置到字符串结束的字符都拷贝到dst[]数组中
//注意这个方法的返回值是void,返回后的字符数组在dst[]中
//实际上是使用System.arraycopy()实现的数组拷贝。而System.arraycopy()底层是使用c++实现的
void getChars(char dst[], int dstBegin) {
System.arraycopy(value, 0, dst, dstBegin, value.length);
}
//该方法是对上面方法的扩充,只是加上了边界检查
//实际上还是使用System.arraycopy()实现的
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
//已过时的方法,但是该代码还是可以学习的
//使用while遍历
@Deprecated
public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
int j = dstBegin; //开始位置
int n = srcEnd; //结束位置
int i = srcBegin; //索引初始为开始位置
char[] val = value; /* avoid getfield opcode */ //复制一份数组,避免直接操作成员变量
while (i < n) {
dst[j++] = (byte)val[i++]; //实现数组拷贝,强制为byte
}
}
//判断当前字符串是否和传入的anObject相等
//这是一个非常重要的方法,重写了Object的equals方法,用来比较字符串内容是否相等。
public boolean equals(Object anObject) {
if (this == anObject) { //如果传入的就是字符串对象本身
return true;
}
if (anObject instanceof String) { //如果传入的是String对象的引用吗,只有两个对象类型相同才有可比性
String anotherString = (String) anObject;
int n = value.length; //n控制while()循环的次数,及当前字符串的长度
if (n == anotherString.value.length) { //如果两字符串长度相等
char v1[] = value;
char v2[] = anotherString.value;
int i = 0; //初始索引为0
while (n-- != 0) {
if (v1[i] != v2[i]) //遍历两个字符数组,如果遇到了不相等的字符,直接返回false
return false;
i++;
}
return true;
}
}
return false;
}
//contentEquals()方法将此字符串与指定的 CharSequence 比较。
//实现方式和上面的equals()方法类似,但是CharSequence是接口。
//String, StringBuffer, StringBuilder等类都实现了CharSequence接口。
public boolean contentEquals(CharSequence cs) {
if (value.length != cs.length())
return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) { //如果参数是StringBuffer或StringBuilder
char v1[] = value;
char v2[] = ((AbstractStringBuilder) cs).getValue();
int i = 0;
int n = value.length;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
// Argument is a String
if (cs.equals(this)) //如果参数是String
return true;
// Argument is a generic CharSequence
// 如果参数是其他实现类的对象
char v1[] = value;
int i = 0;
int n = value.length;
while (n-- != 0) {
if (v1[i] != cs.charAt(i))
return false;
i++;
}
return true;
}
|
|