1.String是一个被final修饰,实现了Serializable,Comparable<String>, CharSequence这三个接口的不可变类
2.String存储字符串在char类型的数组中(private final char[] value),final导致String对象一旦创建,对象不会改变,一般修改都会产生新的对象,对象内容是由System.arraycopy方法生成
3.String对象都会有一个hash值:
public int hashCode() {
int var1 = this.hash;
if (var1 == 0 && this.value.length > 0) {
char[] var2 = this.value;
for(int var3 = 0; var3 < this.value.length; ++var3) {
var1 = 31 * var1 + var2[var3];
}
this.hash = var1;
}
return var1;
}
从代码可以看出生成方式是根据每一个char的值生成的(hashmap的hash方法是更为严谨,会在这个基础上再异或,再位移),这里选择乘数为31的原因是:
1.31是一个不大不小的质数,是作为 hashCode 乘子的优选质数之一。另外一些相近的质数,比如37、41、43等等,也都是不错的选择。那么为啥偏偏选中了31呢
2.31可以被 JVM 优化,31 * i = (i << 5) - i,二进制位移运算相对较为高效
4.String的startWith和compareTo这两个方法的实现和自己写的方式不一样,源码较为容易理解,应借鉴
5.intern方法是一个native方法,用于扩展常量池,扩展了流程:
1.检查常量池是否含有当前字符串,如有就直接返回常量池的引用
2.常量池没有当前对象的字符串,则在常量池新建该常量,并返回该常量池引用,(这里并没有修改原对象的内容)
6.在方法的设计上,String类只自己处理对象创建和字符操作,其余像数组拷贝、编码格式之类的都是委托给了其他实现类,这样结构比较清楚
7.在方法的命名上,一般是名字+介词或者动词+名次(indexOf,valueOf, startWith, checkBounds)
网友评论