目录
一、String概况
1.1 String概述
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
- 被pulic修饰的不可被继承的类
1.2 UML类图
- 实现了Comparable接口,可用于比较String对象大小;
- 实现了Serializable接口,所以String可以实现序列化。
- 实现了CharSequence接口:
- CharSequence接口是一个描述字符串结构的接口;
- 定义了一些对字符串的常用操作;
参考资料:
二、String属性分析
//存放String左右字符的字符数组
private final char value[];
//存放String的hash码值
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
分析:
- 存放String所有字符串的value数组被final修饰,是不可变常量–>String一经实例化即不可在变
- String的hash值是可变的,根据String实例的不同,其hash地址也不同;
三、String方法分析
3.1 构造方法
public String();
public String(String original);
public String(char value[]);
public String(char value[], int offset, int count);
public String(int[] codePoints, int offset, int count);
public String(byte ascii[], int hibyte, int offset, int count);
public String(byte ascii[], int hibyte);
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException;
public String(byte bytes[], int offset, int length, Charset charset);
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException;
public String(byte bytes[], Charset charset);
public String(byte bytes[], int offset, int length);
public String(byte bytes[]);
public String(StringBuffer buffer);
public String(StringBuilder builder);
String(char[] value, boolean share);
String提供多种方式的构造方法,具备不同情况下构造String对象的能力;
3.1.1 String() & String(String original)
public String() {
//将空字符串的值赋值为String的value属性
this.value = "".value;
}
public String(String original) {
//将参数String对象的value和hash赋值给构造的String对象
this.value = original.value;
this.hash = original.hash;
}
如代码所示:
- 在Stirng()中,给String实例赋值为空;
- 在String(String s)构造方法中,将s实例的value和hash赋值给新构造的String实例;
- 由于数组通过“=”赋值是地址引用传递(value指向同一个数组地址),hash是int类型,属于值传递(同一个hash地址),故新构造的String实例与参数String s实例严格来说是同一个对象;
3.1.2 char[] 转 String
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
//count小于0报错,等于0返回空字符串
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
//其实偏移量 + count要小于等于数组长度,否则报错
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
- 字符数组转字符串,底层代码逻辑都是数组新建-字符复制-赋值;
- 通过System.arraycopy(Object src, int srcPos,Object dest, int destPos, int length)实现,该方法是被native修饰的本地方法;
- 在String(char value[], int offset, int count)中,对偏移量和count是有一定要求的:
- offset代表冲字符数组value的那个字符开始复制:起始字符偏移量/索引;
- count代表从字符数value中复制多少个字符:字符数量;
- offset和count都不能小于0;
- offset + count不能大于value的字符总个数;
3.1.3 int[]转String
public String(int[] codePoints, int offset, int count) {
//参数有效性校验
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= codePoints.length) {
this.value = "".value;
return;
}
}
// 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];
//校验int数组中的元素是否在Bmp范围内,是的话一个字符就可以表示
if (Character.isBmpCodePoint(c))
continue;
//判断int数组中的元素在超过bmp范围后,是否在unicode的合理取值范围内
//在合理取值范围内,由于超过了bmp,需要2个字符才能表示一个int数组元素,数组容量+1
//如果没在合理范围内,抛异常
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];
//int数组元素在bmp范围内,直接数组转字符并存放到字符数组中
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else//int数组元素在bmp到合理范围内,一个int数组元素用2个字符表示;
Character.toSurrogates(c, v, j++);
}
this.value = v;
}
- bmp:unicode中 0x0000-0xffff 被称作BMP (Basic Multilingual Plane),char只能表示BMP;
- unicode的合理取值范围:0x0000-0x10ffff,一共21位,二进制
0000 0000 0000 0001 0000 1111 1111 1111 1111;
参考资料:String: public String(int[] codePoints,int offset,int count) 由int数组转化的构造方法