String 源码学习
常见面试题:
String是如何实现的? 有哪些常用的方法?
回答:
以主流的 JDK 版本 1.8 来说,String 内部实际存储结构为 char 数组,Java9 以后String的存储由 char 数组 转换成 byte 数组 (转换后的好处:存储变得更加紧凑,占用内存更少,操作性能更高了),源码如下:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** 用于存储字符串的值. */
private final char value[];
/**缓存字符串的hash code */
private int hash; // Default to 0
// ...其他
}
其它常用的方法:
1、多构造方法
下面是4个重要的构造方法:
/**String 为参数的构造方法*/
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
/**char[] 为参数的构造方法*/
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
/**StringBuffer 为参数的构造方法*/
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
/**StringBuilder 为参数的构造方法*/
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
2、equals() 比较两个字符串是否相等
源码如下:
public boolean equals(Object anObject) {
// 对象引用相同,直接返回 true
if (this == anObject) {
return true;
}
// 判断需要对比的值是否为 String 类型,不是则直接返回 false
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
// 如果字符串的长度,再继续进行下面的比较
if (n == anotherString.value.length) {
// 把两个字符串都转换成 char 类型进行对比
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
// 循环对比两个字符串的每一个字符
while (n-- != 0) {
// 如果有一个字符串不相等,就返回 false,否则就继续对比
if (v1[i] != v2[i])
return false;
i++;
}
// 最后都相等就返回 true
return true;
}
}
return false;
}
简要说明方法的使用:
String 重写了 Object 的 equals() 方法,equals() 方法需要传递一个 Object 类型的参数值,在比较时会先通过 instanceof 判断是否为 String 类型,如果不是则直接返回 false 。 instanceof 的使用为判断 Object 是否为指定的类型,如果是指定的类型返回 true ,不是则返回 false 。
如:
Object str = "abc";
Object a = 123;
System.out.println(str instanceof String); // 返回 true
System.out.println(a instanceof String); // 返回 false
需要注意的一点是: instanceof 只能用作对象的判断(编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定)。 如下面的代码将编译无法通过:
int a = 123;
System.out.println(a instanceof Integer);
System.out.println(a instanceof String);
还有一个与 equals() 比较类似的方法 equalsIgnoreCase(), 用于忽略字符串的大小写之后进行比较。
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true : (anotherString != null) && (anotherString.value.length == value.length) && regionMatches(true, 0, anotherString, 0, value.length);
}
3、compareTo() 比较两个字符串
该方法用于比较两个字符串,返回的结果为 int 类型的值,源码如下:
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
// 获取到两个字符串长度最短的那个 int 值
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;
}
网友评论