好久没有看源码了,这次看看String源码学习知识
继承
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
- 用final来修饰表示string是个最终类,不可被继承
- java.io.Serializable, Comparable, CharSequence 实现了这三个接口,依次是序列化,比较,和字符序列
基本属性
//字符串底层是字符数组
private final char value[];
//哈希值
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
//用于忽略大小写得比较两个字符串。
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
- 字符串的底层是字符数组
构造方法
//默认构造为空字符串
public String() {
this.value = "".value;
}
//将字符串直接赋给字符串
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//如果给定的是字符串数组的话,取该数组前 value.length位的字符
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);
}
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.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
//上面是一系列判断
//该方法是生成一个新的char【】然后赋给value数组,且如果offset+count超过了给定的value【】数组的大小,那么范围取值到value数组的最后一位
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
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());
}
- string的构造函数本质上都是在调用Arrays.copyOf()这个本地方法,创建一个新的字符串数组来返回然后赋值给value数组
一些基本的方法
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
public int length() {
return value.length;
}
public boolean isEmpty() {
return value.length == 0;
}
- 因为字符串的底层是数组,这里就是调用了数组的一些方法
一些字符串的比较方法
//区分大小的比较方法
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
//这里考虑大小写,所以如果不一样直接返回对位字符的差值
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
//不区分大小的比较方法
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}
//
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 8575799808933029326L;
//返回的是整形,二者的插值
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
//统一大写比较
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
//统一小写比较
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
//这里没有结束,返回二者对位字符的差值的差值
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
}
//如果前面相等返回长度的差值
return n1 - n2;
}
public static void main(String[] args) {
char[] chars={'5','5','b'};
String s=new String(chars);
int i = s.compareToIgnoreCase("55a");
//return 1;
System.out.println(i);
}
public static void main(String[] args) {
char[] chars={'5','a','b'};
String s=new String(chars);
int i = s.compareToIgnoreCase("5abcsda");
//return -4;
System.out.println(i);
}
- 不考虑大小写的方法的比较是将对应字符统一大小写后进行比较
- 大小的比较是从头开始比,如果碰到了一个不相同的就结束判断得出大小
判断相不相等
//只需要内容相等就相等
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;
}
//这里会调用 regionMatches 统一大小写后进行判断
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true
: (anotherString != null)
&& (anotherString.value.length == value.length)
&& regionMatches(true, 0, anotherString, 0, value.length);
}
- 比较大小和相同的理念都类似就是挨个字符进行比较,如果有不同的就退出比较。
判断字符第一次出现的位置
//fromIndex起始位置,默认为0
//ch 需要寻找的字符
public int indexOf(int ch, int fromIndex) {
//一些范围判断
final int max = value.length;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
//需要判断是否存在的字符要在Unicode编码里面
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
//定义为final,就算value改变了引用也不会影响到这个字符串
final char[] value = this.value;
//如果找到返回下标,没找到返回-1;
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return indexOfSupplementary(ch, fromIndex);
}
}