您的位置:首页 > 编程语言 > Java开发

JDK源码学习(1)-String

2016-03-14 16:54 453 查看
String类的基本情况

如下是String的类的修饰符:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
...
}
String被修饰为final,决定了String类是不能被继承的。

2.String类的属性:
private final char value[];
由于value使用final进行修饰的,因此决定了String对象创建之后的值不会改变。
所有的属性都是private类型,并且没有实现set方法,因此String中的属性是不能被修改的。

private int hashprivate static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
3.构造函数

这里说如下几个比较特殊的:
1)带编码格式,初始化的值为bytes[]。如下

public String(byte bytes[], int offset, int length, Charset charset) {
...
}
其中charset可以为String类型的编码值。
4.isEmpty 为String的判空方法
public boolean isEmpty() {
return value.length == 0;
}
直接返回判断value是否为0的boolean值。

5.codePointAt 为返回String某个位置上的字符的ascii码十进制数值
public int codePointAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return Character.codePointAtImpl(value, index, value.length);
}
Character.codePointAtImpl方法源码为
static int codePointAtImpl(char[] a, int index, int limit) {
char c1 = a[index];
if (isHighSurrogate(c1) && ++index < limit) {
char c2 = a[index];
if (isLowSurrogate(c2)) {
return toCodePoint(c1, c2);
}
}
return c1;
}
java.lang.Character.isHighSurrogate(char ch)判断给定char值是Unicode高代理项代码单元。也称为高级代理项代码单元)。
这个值并不代表字符本身,而是在UTF-16编码的补充的字符的表示被使用。java.lang.Character.isLowSurrogate(char ch) 确定给定char值是否为一个Unicode低代理项代码单元(也称为尾部代理项代码单元)。
这些值并不代表本身的字符,但用于表示增补字符的UTF-16编码。6.equals

该方法是Object类的方法重写,代码如下
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
equals主要判断条件为:
1)判断对象是否为同一个,如果是同一个则返回true;
2)如果比较对象为String,判断两个String的length即长度是否相同,不相同返回flase;
3)如果两个String的length相同,那么遍历比较所有位置的char的值,如果有不相同的地方,则返回false。遍历结束没有不同之处,则返回true;
4)如果不满足同一个对象,也不都是String的类型,那么返回flase。

7.compareTo
源码:
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
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;
}
规则:
1)从第一位字符开始比较两个String类型,如果有不同之处,则返回两个字符的比较结果。
2)如果一直到两个字符中较短字符串遍历完还没有结果,那么就直接比较两个字符的值。并将两值相减的结果返回。

8.hashcode
源码:
public int hashCode() {
//hash默认为0;
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;

for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
可重写该方法,为了业务的具体使用。
解析:hash默认为0,hashcode的逻辑主要为:∑(val
*31^(length-n-1))
9.join,该特性从java7开始
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
该类主要是功能为: join("_","java","clean")结果为"java_clean"

//初始化joiner
StringJoiner joiner = new StringJoiner(delimiter);
//具体实现
public StringJoiner(CharSequence delimiter) {
this(delimiter, "", "");
}
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
Objects.requireNonNull(prefix, "The prefix must not be null");
Objects.requireNonNull(delimiter, "The delimiter must not be null");
Objects.requireNonNull(suffix, "The suffix must not be null");
// make defensive copies of arguments
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
this.emptyValue = this.prefix + this.suffix;
}

joiner.add(cs);
//具体实现如下,每次调用会先追加delimiter,然后在追加newElement,则可以拼出想要的串
public StringJoiner add(CharSequence newElement) {
prepareBuilder().append(newElement);
return this;
}

private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
} else {
value = new StringBuilder().append(prefix);
}
return value;
}
10.trim
public String trim() {
int len = value.length;
int st = 0;
char[] val = value;    /* avoid getfield opcode */

while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
该方法主要是去掉头尾的空格。小于‘ ’的字符也为空字符。 空字符的值为32
11.replace与replaceAll首先运行测试代码如下:
String string="asdfv123456asdfxcz";
System.out.println(string.replace("123456", "OK"));
System.out.println(string.replaceAll("123456", "OK"));

String string1="asdfv@#$%^&asdfxcz";
System.out.println(string1.replace("@#$%^&", "OK"));
System.out.println(string1.replaceAll("@#$%^&", "OK"));
结果为:
asdfvOKasdfxcz
asdfvOKasdfxcz
asdfvOKasdfxcz
asdfv@#$%^&asdfxcz
可以看到针对特殊符号来说,replaceAll没有正常替换成功。replace代码为:
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */

while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
可以看到,该方法通过遍历String所有的元素,如果找到符合条件的元素则进行替换。其中如“aaa” 将“aa”替换成“b”则结果为“ba”而非“ab”
replaceAll代码为:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
主要是针对正则表达进行替换,如下面代码:
String string="asdfv123456asdfxcz";
String string1="asdfv@#$%^&asdfxcz";
System.out.println(string.replaceAll("\\d", "*"));
System.out.println(string1.replaceAll("\\d", "*"));
结果为:
asdfv******asdfxcz
asdfv@#$%^&asdfxcz
因此可以看到,
replaceAll("\\d", "*")
主要作用为将字符串中所有的数字字符转换成“*”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: