本文分析的为JDK7中的String类
String类:
这里可以看出String被final修饰,是个不可变量,线程安全的,并且不允许被继承。
并且实现了Serializable(可以进行序列化和反序列化),Comparable(可以进行自定义的字符串比较),CharSequence(一个可读序列)接口。
String属性:
这里包含两个属性,一个不可变的char数组,说明String本身就是一个字符数组。
另一个是String的hash值,默认为0。
String方法:
这里挑选一些比较常用和重要的方法进行解释
首先是构造方法:去掉了将删除的方法,后面的方法没有解释,相信大家基本都能看懂
//默认构造方法,一般不用,因为String字符串是不可改变的
public String() {
this.value = new char[0];
}
//使用已存在的一个字符串创建一个相同字符序列的字符串
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//使用一个字符数组创建一个字符串
public String(char value[]) {
//复制字符数组并赋值给value
this.value = Arrays.copyOf(value, value.length);
}
//使用字符数组的一部分创建一个字符串对象 offset为字符数组开始位置,count为数组开始位置往后的长度
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
//将int数组转换成String,offset为数组开始位置,count为数组开始位置往后的长度
public String(int[] codePoints, 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 > codePoints.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
final int end = offset + count;
// Pass 1: Compute precise size of char[]
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
continue;
else if (Character.isValidCodePoint(c))
n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
final char[] v = new char[n];
for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else
Character.toSurrogates(c, v, j++);
}
this.value = v;
}
//将字节数组转成String,charsetName为编码格式
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charsetName, bytes, offset, length);
}
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charset, bytes, offset, length);
}
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
}
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
public String(byte bytes[]) {
this(bytes, 0, bytes.length);
}
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
常用方法:
//返回字符串长度
public int length() {
return value.length;
}
//判断字符串是否为空
public boolean isEmpty() {
return value.length == 0;
}
//根据下标获取字符
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
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值乘31+该字符
}
hash = h;
}
return h;
}
//判断值是否相等
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
//本地方法
public native String intern();
后面的慢慢补充
intern方法特别解释一下: String的intern()方法的原理,在调用此方法时候会初始化一个空的字符串池,然后将该字符串对象加入该池中,当再次调用这个方法的时候,会判断这个池中是否包含字符串,如果包含则从池中返回这个字符串,否则加入这个字符串并返回这个字符串对象的引用,如果在线程中用String锁,可能需要用到这个方法。