String类源码分析
源码版本为java8
源码解析
- 实现Serializable接口,Comparable接口,CharSequence接口
- Serializable 接口: 可序列化对象接口 接口内无函数
- comparable 接口: 比较器接口 内有compareTo方法
- CharSequence: 字符序列 length,charAt,subSequence等方法
- 属性
- final 类型的 char数组 value
- 序列化id
- int hash
- 构造方法
- String()
- String (String) -> 赋值value 和 hash 值
- String (char []) -> 使用Arrays工具类复制一个数组赋值给value
- String (char[], offset, count) -> Arrays.copyOfRange(value, offset, offset+count)
- 常用方法
- length() -> 返回 value.length
- equals() -> 1.判断是否是String类型 2.是否长度相等 3.每一个字符是否相等
- getByte() -> 直接返回value数组
- compareTo() -> 从第0位比较两个字符的值 如果相同比较下一位 都相同则length长的大
- indexOf(int char) -> 从第0位比较字符,相等返回位置
- indexOf(String string) -> 双循环比较两个String的value字符数组,第一位相同的时候往后比较每一位的值是否相等 具体实现为indexOf(char[],int ,int,char[],int,int)方法
- lastIndexOf() -> 从最后开始比较 和 indexOf 相似
- subSting () -> 根据String的String(String, begin, end)构造方法返回新的String,需要用一个对象接收新的String对象,原有的String不可变,还是为原来的值,String 对象不可变!
- toLowerCase() -> 对照asall码,将在大写的字母范围内的都变成小写
- trim() -> 找到第一个不为’ '的字符和最后一个不为‘ ’的字符,假如第一位=0 最后一位 = value.length,则返回原String, 否则调用new String(Stirng,begin, end)创建一个新的String
- intern() -> native 本地方法 和虚拟机JVM的本地方法相关
- split() -> 单个字符截断使用subString截断,多String调用Pattern.compile(regex)然后递归
源码片段
- byte数组转String
public String(byte ascii[], int hibyte, int offset, int count) {
checkBounds(ascii, offset, count);
char value[] = new char[count];
if (hibyte == 0) {
for (int i = count; i-- > 0;) {
//将每一位和0xff比较 0xff 转换成2进制为1111 1111 两个都为1则为1 其他的为0,所以只留下最后8位(一个字节)
value[i] = (char)(ascii[i + offset] & 0xff);
}
}
else {
hibyte <<= 8;
for (int i = count; i-- > 0;) {
value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
}
}
this.value = value;
}
public String[] split(String regex, int limit) {
char ch = 0;
/*
用一个字符隔断string
进入循环的条件
1. 长度为1 没有正则相关的字符
2. 长度为2 第一个是转义字符 且非数字和字母
*/
if (((regex.value.length == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
list.add(substring(off, value.length));
off = value.length;
break;
}
}
// If no match was found, return this
if (off == 0)
return new String[]{this};
// Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, value.length));
// Construct result
int resultSize = list.size();
if (limit == 0) {
while (resultSize > 0 && list.get(resultSize - 1).length() == 0)
{
resultSize--;
}
}
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
}
心得
- String的内容为里面的final 类型的char 数组,所以String的对象是不可变的
- 同一个类的私有属性,不同的对象在自己的类里面的方法可以直接调用私有对象
- eg: value = otherString.value
- & 与字符 两个为1的时候结果才是1
- 0xff 为16进制 转换成2进制为1111 1111,所以 & 0xff 保留8位小数
- “>> x 右移运算符 (*2^-x) 左移同理”
- 方法里面尽量将不符合条件的直接返回错误或者false 减少方法消耗的时间和性能
- 重载方法相同的尽量将主要逻辑写在最复杂的方法中,逻辑代码尽量只写一份