前言
个人见解,有理解错误的地方望指正。
概述
Java中用来创建和操作字符串的类,一个不可变的类。
类的定义
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
- 刚刚上面说到String是一个不可变的类,这里可以看到String类是用final修饰的,是一个不可继承不可变的类
- 实现了Serializable接口,表示这个类可以被序列化
- 实现Comparable接口,默认的比较器,用来比较两个字符的大小,实现了这个接口意味着类支持排序(按照实现方法内的规则排序),可以使用Collections.sort()或者Arrays.sort()等方法。
- 实现了CharSequence接口,表示是一个有序的字符集合,提供了对序列字符的一些操作。
属性
//存储字符串的数组
//也是使用final修饰的,所以String还是不可变的,不可变只是指数组的引用不可变
//数组是一段连续的内存地址,里面的某个值还是可以变的
private final char value[];
//缓存字符串的hash代码
private int hash;
//序列化编号
private static final long serialVersionUID = -6849794470754667710L;
//也是用来参与序列化的一个属性
private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];
常见构造方法
- String()
//无参构造函数,创建一个空的字符串对象
public String() {
this.value = "".value;
}
- String(String original)
//入参一个String类型,将String的value和hash都赋值给新的String
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
- String(char value[])
//入参一个char类型的数组,使用Arrays.copy()将参数数组的长度和内容赋值给新的该String的value
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
- String(char value[], int offset, int count)
//入参一个char类型数组,将数组从下标offset开始复制count个,再赋值String的value
public String(char value[], int offset, int count) {
//如果起始下标小于0,抛出异常
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
//如果复制长度小于0,抛出异常
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
//如果复制长度=0,且起始下标<=数组长度,创建一个空的数组
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// 如果起始下标大于数组长度-数组长度,抛出异常
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
//调用copyOfRange方法复制数组
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
- String(byte bytes[], int offset, int length, String charsetName)
//从bytes[]数组的offset位置截取长度为length的字符,以charsetName编码复制给String的value
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);
}
- String(StringBuffer buffer)
//入参一个String Buffer对象,将buffer的长度和内容复制给Sting的vlaue数组
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
- String(StringBuilder builder)
//和上面一样
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
常用方法
- length():
//返回当前字符串长度,构造比较简单,直接返回了value数组的长度
public int length() {
return value.length;
}
- isEmpty():
//判断字符串是否为空,判断value的长度是否等于0,如果为0则返回false,否则返回true
public boolean isEmpty() {
return value.length == 0;
}
- charAt(int index):
//获取字符串中的index索引处的值
public char charAt(int index) {
//判断索引值是否超过数组长度,超过则抛出异常
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
//否则返回数组中索引对应的值
return value[index];
}
- equals:
- equals(Object object):
//将字符串和指定的对象作比较,如果相等返回true,否则返回false
public boolean equals(Object anObject) {
//先直接用==判断,即两个对象指向的引用地址是否是同一个,如果是直接返回true
if (this == anObject) {
return true;
}
//判断是否是String类型的
if (anObject instanceof String) {
//转换为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])
//只要有一个不相等就返回false
return false;
i++;
}
//否则返回true
return true;
}
}
//如果不是String类型直接返回false
return false;
}
- equalsLgnoreCase(String value):
//忽略大小写,将String与另一个String字符串作比较
public boolean equalsIgnoreCase(String anotherString) {
//如果指向同一地址,直接返回true,否则就判断字符串不为空,且两个字符串长度相同且字符相同
return (this == anotherString) ? true
: (anotherString != null)
&& (anotherString.value.length == value.length)
&& regionMatches(true, 0, anotherString, 0, value.length);
}
/**
ignoreCase:是否忽略大小写
tooffset:当前字符串起始位置
other:要比较的字符串
ppffset:参数字符的起始位置
len:要比较的字符数
**/
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) {
char ta[] = value;
int to = toffset;
char pa[] = other.value;
int po = ooffset;
// 先判断起始位置是否正确
if ((ooffset < 0) || (toffset < 0)
|| (toffset > (long)value.length - len)
|| (ooffset > (long)other.value.length - len)) {
return false;
}
//循环判断字符是否相等
while (len-- > 0) {
char c1 = ta[to++];
char c2 = pa[po++];
//如果==判断为真,直接跳出循环进入下一次循环
if (c1 == c2) {
continue;
}
//否则判断是否需要忽略大小写
if (ignoreCase) {
//将字符转换为大写,再做比较
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
//转换为小写作比较
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
}
//不满足返回false
return false;
}
return true;
}
- compareTo
- compareTo(String str)
//按字典顺序比较两个字符串
//如果当前字符串等于参数字符串返回0
//如果当前字符串小于参数字符串,返回负数
//如果当前字符串大于参数字符串,返回正数
public int compareTo(String anotherString) {
//获取当前字符串的长度
int len1 =