JDK源码分析:java.lang.String
最近开始看JDK源码,不能太懒了~~注释非常详细(虽然是英文),而且部分代码也不算很复杂。先挑的简单的看看。。为了坚持下去,所以在博客写些记录,一是为了记忆,二是给自己一个坚持的理由~~哇咔咔,英文不算很好,那就对着中文API一起看吧。。
String结构
这个类结构很简单。。
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
用了一个char数组来存储字符,然后offset是偏移(这个我还搞不懂有啥用),count是String的长度。
注意到String类是final的,不可以被继承,而且private final char value[];,只能赋值一次,赋值后就不能变了,只有从新生成一个String对象。
public String concat(String str)
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
这段代码是连接两个String的,先拿个char数组当容器,从this和str分别取出char放入buf内,注意getChars方法的第四个参数,这个是说buf从count个开始拷贝。也就是说把两个string的char放在了一个char数组内,再返回一个新的String对象。(因为之前的String已经不可以改变)
public int indexOf(String str, int fromIndex)
public int indexOf(String str, int fromIndex) {
return indexOf(value, offset, count,
str.value, str.offset, str.count, fromIndex);
}
//source源字符,sourceOffset源偏移,sourceCount源长度
//target查找的字符 ...
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
//如果fromIndex比源字符还长(从0算起),并且查找的字符长度为0,那就返回源字符的长度,否则返回-1
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
//如果fromIndex比源字符短,查找的字符长度为0,直接返回fromIndex
if (targetCount == 0) {
return fromIndex;
}
//先取出第一个字符
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
//循环每一个字符
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* 直到找到第一个字符 */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* 找到第一个字符后,比较剩下的字符 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j] ==
target[k]; j++, k++);
if (j == end) {
/* 如果j能到end,那就说明找到整个字符串啦,返回偏移 */
return i - sourceOffset;
}
}
}
return -1;
}
indexOf只要看它的查找方法,先找到第一个,然后再匹配剩下的。
public boolean equals(Object anObject)
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
比较char~~
replace与replaceAll
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
这两句真短啊。。用正则表达式来替换的。可以看出他们的区别。
replace只支持普通字符的替换哦,Pattern.LITERAL是指启用模式的字面值解析。Matcher.quoteReplacement(str)返回指定 String 的字面值替换 String。这个方法也就是替换\\为\\\\(四个反斜杠),$换为\\$。这样,它就不能用正则表达式了,但是看到依然是replaceAll,替换所有。
replaceAll很简单的一个正则表达式使用~~
要注意的是源字符串替换后内容并没有发生变化。
举例如下: 来源
String src = new String(“ab43a2c43d”);
System.out.println(src.replace(“3″,”f”));=>ab4f2c4fd.
System.out.println(src.replace(’3′,’f'));=>ab4f2c4fd.
System.out.println(src.replaceAll(“\\d”,”f”));=>abffafcffd.
System.out.println(src.replaceAll(“a”,”f”));=>fb43fc23d.
System.out.println(src.replaceFirst(“\\d,”f”));=>abf32c43d
System.out.println(src.replaceFirst(“4″,”h”));=>abh32c43d.
如果你喜欢本文, 请长按二维码,关注公众号 分布式编程.
作者:分布式编程
出处:https://zthinker.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。