写在前面
说说这几天看源码的感受吧,其实 jdk
中的源码设计是最值得进阶学习的地方。我们在对 api
较为熟悉之后,完全可以去尝试阅读一些 jdk
源码,打开 jdk
源码后,如果你英文能力稍微过得去,那么源码有相当详细的注释告诉你 api
的含义,具体用法。假设平时在写代码的过程中突然忘记了某个 api
的用法,那么有些新手没读过源码的可能顺手就打开百度或者谷歌,搜索 api 怎么用?哈哈哈,面向谷歌编程,这样的状态可能会让你一年的经验重复n
年, 如果是阅读过源码,则直接进去看看源码英文注释,回想一下源码的实现即可使用,而且看过源码后,里面有些代码细节是可以在平时编码的过程中直接借鉴的。
废话有点多啦~~滴滴滴,上车了。。。
上一篇 String 源码浅析(一) 中已经对String
前半部分源码做了解析,这篇把剩下的方法粗略的总结下…
String 成员方法
- 判断字符串是否相等,该方法继承自
Object
类的重写实现,原则上也是比较字符串中的字符是否相等。
1 public boolean equals(Object anObject) {
2 //判断形参跟当前字符串对象地址是否相等,即是否为同一个对象,如果相等,则返回true
3 if (this == anObject) {
4 return true;
5 }
6 //如果形参为String类型对象
7 if (anObject instanceof String) {
8 //强转为String类型对象
9 String anotherString = (String)anObject;
10 //当前字符串对象的字符数组长度
11 int n = value.length;
12 //如果当前字符串对象的字符数组长度等于形参字符串字符数组长度
13 if (n == anotherString.value.length) {
14 //当前字符串字符数组
15 char v1[] = value;
16 //形参字符串字符数组
17 char v2[] = anotherString.value;
18 //遍历索引起始位置0
19 int i = 0;
20 //遍历当前字符串字符数组,每个索引位置的字符与形参字符串索引位置字符比较,如果不相等则返回false
21 while (n-- != 0) {
22 if (v1[i] != v2[i])
23 return false;
24 i++;
25 }
26 return true;
27 }
28 }
29 //以上条件都不满足,最后返回false
30 return false;
31} - 传入
CharSequence
接口形参,实际是与StringBuffer
,StringBuilder
比较是否相等,因为StringBuffer
,StringBuilder
都实现了CharSequence
接口
1public boolean contentEquals(CharSequence cs) {
2 //判断形参是否是AbstractStringBuilder抽象类,实则因当传入的是其子类:StringBuffer, StringBuilder
3 if (cs instanceof AbstractStringBuilder) {
4 //如果形参是StringBuffer类型对象
5 if (cs instanceof StringBuffer) {
6 //同步锁,调用nonSyncContentEquals方法比较两种是否相等
7 synchronized(cs) {
8 return nonSyncContentEquals((AbstractStringBuilder)cs);
9 }
10 } else {
11 //如果形参对象是StringBuilder,则调用nonSyncContentEquals方法比较两种是否相等
12 return nonSyncContentEquals((AbstractStringBuilder)cs);
13 }
14 }
15 // 如果形参是String对象,则直接调用equals方法返回
16 if (cs instanceof String) {
17 return equals(cs);
18 }
19 // 如果是其他的CharSequence实现类,则遍历,一个个字符进行比较,找到一个字符不相等则直接返回false
20 char v1[] = value;
21 int n = v1.length;
22 if (n != cs.length()) {
23 return false;
24 }
25 for (int i = 0; i < n; i++) {
26 if (v1[i] != cs.charAt(i)) {
27 return false;
28 }
29 }
30 //以上代码都不成立,走到最后直接返回true
31 return true;
32} - 私有方法,非同步方式(线程不安全)比较与 AbstractStringBuilder 是否相等,实则是与其子类:StringBuffer, StringBuilder 比较大小,
contentEquals(CharSequence cs)
方法中核心比较代码就是调用该方法。
1 private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
2 //当前字符串对象字符数组
3 char v1[] = value;
4 //获取形参字符数组
5 char v2[] = sb.getValue();
6 //当前字符串对象字符数组长度
7 int n = v1.length;
8 //如果当前字符串对象字符数组长度不等于形参字符数组长度,则直接返回false
9 if (n != sb.length()) {
10 return false;
11 }
12 //遍历当前字符串对象字符数组,与形参字符数组逐一比较字符,找到一个字符不相等,则直接返回false
13 for (int i = 0; i < n; i++) {
14 if (v1[i] != v2[i]) {
15 return false;
16 }
17 }
18 //以上条件都不成立,代码走到最后则直接返回true
19 return true;
20} - 公有方法,比较与
StringBuffer
对象是否相等,内部实则直接调用的contentEquals(CharSequence cs)
方法,可以说该方法是StringBuffer
的特别版吧。
1 public boolean contentEquals(StringBuffer sb) {
2 return contentEquals((CharSequence)sb);
3} - 匹配两个字符串部分片段是否相等
1 public boolean regionMatches(int toffset, String other, int ooffset,
2 int len) {
3 //当前字符串字符数组
4 char ta[] = value;
5 //当前字符串开始比较的起始位置,即偏移量
6 int to = toffset;
7 //待比较的字符串字符数组
8 char pa[] = other.value;
9 //待比较的字符串起始位置,即偏移量
10 int po = ooffset;
11 //索引检查 1.偏移量小于0 2. 偏移量大于总长度-待比较的长度
12 //以上两种情况直接返回false
13 if ((ooffset < 0) || (toffset < 0)
14 || (toffset > (long)value.length - len)
15 || (ooffset > (long)other.value.length - len)) {
16 return false;
17 }
18 //遍历,找出不相等的字符,则返回false
19 while (len-- > 0) {
20 if (ta[to++] != pa[po++]) {
21 return false;
22 }
23 }
24 //不出意外,最终则返回true
25 return true;
26} - 匹配两个字符串部分片段是否相等,同时判断是否忽略大小写
1public boolean regionMatches(boolean ignoreCase, int toffset,
2 String other, int ooffset, int len) {
3 //当前字符串字符数组
4 char ta[] = value;