String源码解析
本章源码分析基于JDK1.7
实现的接口
String类被final修饰词修饰,代表不可修改的特性,它实现了三个接口,Serializable是序列化接口,Compareble是排序接口,Char是字符序列接口。
public final class String implements Serializable, Comparable<String>, CharSequence
主要成员变量
char[]:String通过char[]来实现String的各种功能,字符串由字符数组实现。
hash:用于缓存hash值,因为String类是final不可修改的,所以hash值也是固定的,为了避免重复计算hash值而缓存。
CASE_INSENSITIVE_ORDER:排序器,由上可知String类实现了Compareble接口,这里的Comparator用于忽视大小写的字符串的比较。
private final char[] value;
private int hash;
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator();
构造函数
String共有15个重载构造函数,入参这几种:空、char[]、String、StringBuffer、StringBuilder、byte[],通过这些来构造字符串对象。
//第一种,入参为空,新建了大小为0的char数组,这就是空字符串
public String() {
this.hash32 = 0;
this.value = new char[0];
}
//第二种,入参为String对象,直接将入参的属性复制过来
public String(String var1) {
this.hash32 = 0;
this.value = var1.value;
this.hash = var1.hash;
}
//第三种,入参为char[],将value赋值为入参var1
public String(char[] var1) {
this.hash32 = 0;
this.value = Arrays.copyOf(var1, var1.length);
}
//第四种,入参为char[],截取char[]中从var2到var3的字符作为字符串
public String(char[] var1, int var2, int var3) {
this.hash32 = 0;
if (var2 < 0) {
throw new StringIndexOutOfBoundsException(var2);
} else if (var3 < 0) {
throw new StringIndexOutOfBoundsException(var3);
} else if (var2 > var1.length - var3) {
throw new StringIndexOutOfBoundsException(var2 + var3);
} else {
this.value = Arrays.copyOfRange(var1, var2, var2 + var3);
}
}
public String(int[] var1, int var2, int var3) {
this.hash32 = 0;
if (var2 < 0) {
throw new StringIndexOutOfBoundsException(var2);
} else if (var3 < 0) {
throw new StringIndexOutOfBoundsException(var3);
} else if (var2 > var1.length - var3) {
throw new StringIndexOutOfBoundsException(var2 + var3);
} else {
int var4 = var2 + var3;
int var5 = var3;
int var7;
for(int var6 = var2; var6 < var4; ++var6) {
var7 = var1[var6];
if (!Character.isBmpCodePoint(var7)) {
if (!Character.isValidCodePoint(var7)) {
throw new IllegalArgumentException(Integer.toString(var7));
}
++var5;
}
}
char[] var10 = new char[var5];
var7 = var2;
for(int var8 = 0; var7 < var4; ++var8) {
int var9 = var1[var7];
if (Character.isBmpCodePoint(var9)) {
var10[var8] = (char)var9;
} else {
Character.toSurrogates(var9, var10, var8++);
}
++var7;
}
this.value = var10;
}
}
/** @deprecated */
@Deprecated
public String(byte[] var1, int var2, int var3, int var4) {
this.hash32 = 0;
checkBounds(var1, var3, var4);
char[] var5 = new char[var4];
int var6;
if (var2 == 0) {
for(var6 = var4; var6-- > 0; var5[var6] = (char)(var1[var6 + var3] & 255)) {
;
}
} else {
var2 <<= 8;
for(var6 = var4; var6-- > 0; var5[var6] = (char)(var2 | var1[var6 + var3] & 255)) {
;
}
}
this.value = var5;
}
/** @deprecated */
@Deprecated
public String(byte[] var1, int var2) {
this(var1, var2, 0, var1.length);
}
private static void checkBounds(byte[] var0, int var1, int var2) {
if (var2 < 0) {
throw new StringIndexOutOfBoundsException(var2);
} else if (var1 < 0) {
throw new StringIndexOutOfBoundsException(var1);
} else if (var1 > var0.length - var2) {
throw new StringIndexOutOfBoundsException(var1 + var2);
}
}
public String(byte[] var1, int var2, int var3, String var4) throws UnsupportedEncodingException {
this.hash32 = 0;
if (var4 == null) {
throw new NullPointerException("charsetName");
} else {
checkBounds(var1, var2, var3);
this.value = StringCoding.decode(var4, var1, var2, var3);
}
}
public String(byte[] var1, int var2, int var3, Charset var4) {
this.hash32 = 0;
if (var4 == null) {
throw new NullPointerException("charset");
} else {
checkBounds(var1, var2, var3);
this.value = StringCoding.decode(var4, var1, var2, var3);
}
}
public String(byte[] var1, String var2) throws UnsupportedEncodingException {
this(var1, 0, var1.length, (String)var2);
}
public String(byte[] var1, Charset var2) {
this(var1, 0, var1.length, (Charset)var2);
}
public String(byte[] var1, int var2, int var3) {
this.hash32 = 0;
checkBounds(var1, var2, var3);
this.value = StringCoding.decode(var1, var2, var3);
}
public String(byte[] var1) {
this((byte[])var1, 0, var1.length);
}
public String(StringBuffer var1) {
this.hash32 = 0;
synchronized(var1) {
this.value = Arrays.copyOf(var1.getValue(), var1.length());
}
}
public String(StringBuilder var1) {
this.hash32 = 0;
this.value = Arrays.copyOf(var1.getValue(), var1.length());
}
String(char[] var1, boolean var2) {
this.hash32 = 0;
this.value = var1;
}
/** @deprecated */
@Deprecated
String(int var1, int var2, char[] var3) {
this(var3, var1, var2);
}
length方法
通过获取char[]的长度来获取字符串的长度
public int length() {
return this.value.length;
}
isEmpty方法
通过判断char[]的长度是否为0来判断是否为空
public boolean isEmpty() {
return this.value.length == 0;
}
charAt方法
通过char[]数组下标获取到对应位置的char字符
public char charAt(int var1) {
if (var1 >= 0 && var1 < this.value.length) {
return this.value[var1];
} else {
throw new StringIndexOutOfBoundsException(var1);
}
}
equals方法
首先比较内存地址,再判断是否是String类型,然后再判断长度,最后逐个比较其中的char。
public boolean equals(Object var1) {
//首先比较内存地址
if (this == var1) {
return true;
} else {
//判断var1是否是String类型
if (var1 instanceof String) {
//如果是则强转
String var2 = (String)var1;
//获取当前String中char[]的长度
int var3 = this.value.length;
//如果传入的var1和当前String中char[]的长度一样
if (var3 == var2.value.length) {
char[] var4 = this.value;
char[] var5 = var2.value;
//将传入的var1和当前字符串中char[]中字符逐个比较,若有一个不一致则返回false
for(int var6 = 0; var3-- != 0; ++var6) {
if (var4[var6] != var5[var6]) {
return false;
}
}
return true;
}
}
return false;
}
}
hashCode方法
这里的hash值计算有个特点,就是String内部缓存了hash值,如果hash值不为0则直接返回,不需要再次进行计算,因为String是被final修饰的,它不会被修改,所以没有必要每次都重新计算hash值。
public int hashCode() {
//首先从String的成员变量hash获取到hash值
int var1 = this.hash;
//如果hash值为0且当前String不为空
if (var1 == 0 && this.value.length > 0) {
//获取到当前String的char[]
char[] var2 = this.value;
//逐个使用char循环叠加计算hash值
for(int var3 = 0; var3 < this.value.length; ++var3) {
var1 = 31 * var1 + var2[var3];
}
//计算好后将hash值赋值给成员变量hash
this.hash = var1;
}
//最后返回hash值
return var1;
}
compareTo方法
通过两个字符串的第一个不一样的字符来比较大小并返回结果,若两个字符串的字符都一样则比较两个字符串的长度。
public int compareTo(String str) {
//分别获取到当前String和传入String的length
int thisLen = this.value.length;
int strLen = str.value.length;
//计算出两个String最小的长度minLen
int minLen = Math.min(thisLen, strLen);
char[] thisValue = this.value;
char[] strValue = str.value;
//循环找出两个字符串第一个不一样的字符比较大小并返回比较结果
for(int i = 0; i < minLen; ++i) {
char thisChar = thisValue[i];
char strChar = strValue[i];
if (thisChar != strChar) {
return thisChar - strChar;
}
}
//若两个字符串循环比较的字符是一样的,那么使用字符串长度来比较大小
return thisLen - strLen;
}
本文地址:https://blog.csdn.net/w8827130/article/details/88932467
上一篇: Java中的方法重载、重写、隐藏
下一篇: SimpDateFormat类详解