学习目标:
Java基础内容学习
学习内容:
String类的基本使用和实现原理
- String类的基本使用
- String类的实现原理
一、String类的基本使用
1、String类的常用API
String是字符串类有concat(String str)、equals(Object obj)、split(String regex)、substring(int beginIndex)、compareTo(String anotherString)、toLowerCase()|toUpperCase()等很多常用API。
但对其中的equals(Object obj)进行了重写:
equals(Object obj)方法源于Object根类,默认是在比较两个对象的内存地址是否一致。
public boolean equals(Object obj) {
return (this == obj);
}
不同的类重写equals()方法以达到不同的效果,其中String类重写equals()方法用于只比较字符串内容是否一致。
注意:一般重写equals(Object obj)都需要重写hashCode()方法!
原因是:字符串对象可以被重用以节省内存,String重写equals(Object obj)就是为了只比较字符串内容,如果没有重写hashCode()方法,两个相同的String字符串可能会得到两个不同的hashCode,继而违背了重用的初衷。
二、String类的实现原理
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
... ...
}
通过阅读源码可知,String是由final修饰的,那必然是不可变的,同时String还实现了Serializable与Comparable等接口,那应该会有序列化和比较等功能。
既然String是不可变的,那其API是如何实现字符串扩充和缩减操作的:
主要有两种方式:
1、其一是通过可变字符串工具作为中间态进行长度扩充和缩减,再转换为String类,以replaceAll()方法为例,源码如下:
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuffer sb = new StringBuffer();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString();
}
return text.toString();
}
方法内新建一个StringBuffer可变字符串工具,复制源字符串内容,进行替换操作后得到目标字符串后,调用toString()方法。
扩展:中间态工具为什么选择StringBuffer,而不选择StringBuilder?
原因是:StringBuilder是非线程安全的,在并发多线程环境下,可能产生数据错误,StringBuffer是线程安全的,其重要方法都是用synchronized修饰,保障了数据操作的原子性,以delete()方法为例
@Override
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
super.delete(start, end);
return this;
}
2、其二是通过数组拷贝原字符串内容,再将字符数组作为入参构造一个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);
}
3、split()的使用
调用:String[] split = str.split(“\|”);
3.1正则表达式多次匹配
- 入参是一个正则表达式,方法内部会创建一个ArrayList
- 每次匹配,内容都会新增到list上
- 创建一个String[] 数组,将list的值copy到数组上
ArrayList<String> list = new ArrayList<>();
list.add(substring(off, next));
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
3.2 正则表达式只匹配一次
会直接创建一个String[] 数组,数组只有一个元素,就是字符串自己本身
if (off == 0)
return new String[]{this};