只是简单谈谈,没啥可说的,不全面覆盖
- String为final类不能被继承。其实就是一个final的char数组。
- 看看好多人都比较困惑的字符串比较问题。
// original = "你好吗"
private static void t1(String original) {
String o = "你好吗";
String j = o;
String j1 = new String(o);
StringBuilder j2 = new StringBuilder(original);
System.out.println(original == o);
System.out.println(original == j);
System.out.println(original.equals(j));
System.out.println("=====");
System.out.println(original == j1);
System.out.println(original.equals(j1));
System.out.println("=====");
System.out.println(j.equals(j2));
System.out.println(j.contentEquals(j2));
System.out.println("=====");
//System.out.println("abc".equals("ABC"));
//System.out.println("abc".equalsIgnoreCase("ABC"));
}
输出:
true 比较引用地址
true 比较引用地址
true 看equals源码,比较引用地址
=====
false j1 对象指向的是一块新的内存地址,所以 == 比较后地址不同返回 false
true 看 equals 源码,在判断(if (anObject instanceof String)) j1 为 String 类型后,采用相同角标循环遍历判断2个 char 数组中的值是否相同。比较后值相同返回 true
=====
false 首先 j2 是一个 StringBuilder 类型的对象。再看 equals 源码,得知此方法有2处判断,第一为几类型引用地址判断,第二种为是否是 String 类型判断。因为 j2 为一个 StringBuilder 类型,j2 的引用又与 j 的不同,所以该方法返回 false
true 这怎么就又为 true 了呢?查看 contentEquals 源码可知,StringBuilder 继承了 AbstractStringBuilder ,所以 j2 为 AbstractStringBuilder 类型,然后根据类型判断进入到了 nonSyncContentEquals() 方法,首选判断长度,其次比较相同索引下 char 数组中的值。所以返回 true
=====
源码如下:
public boolean equals(Object anObject) {
// 基本类型比较或者比较对象的引用地址
if (this == anObject) {
return true;
}
// 判断 anObject 是否为 String 类型
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) {
// 比对2个 char 数组中每个位置上的值是否相等,如有不等,返回 false
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
int n = v1.length;
if (n != sb.length()) { // 长度不匹配,2串不相等
return false;
}
for (int i = 0; i < n; i++) { // 相同角标值不同,2串不相等
if (v1[i] != v2[i]) {
return false;
}
}
return true;
}
- 说一下
concat
这个方法。其实很简单,通过2次数组的复制就可以实现。第一次为扩容char
数组,第二次为填充要concat
的char
数组内容。
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
// 把之前的 char 数组拷贝到新的数组后返回
char buf[] = Arrays.copyOf(value, len + otherLen);
// 把 str 的 char 数组添加到从 len 开始的位置上
str.getChars(buf, len);
return new String(buf, true);
}
void getChars(char dst[], int dstBegin) {
System.arraycopy(value, 0, dst, dstBegin, value.length);
}
- 看一下
JDK 1.8
新加的一个小玩意 。意思是返回一个由elements
被delimiter
分割的字符串
public static String join(CharSequence delimiter, CharSequence... elements)
public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
private static void t2(String original) {
System.out.println(String.join(",","a","b", "c", "d"));
String[] strings = {"我", "爱", "小", "二", "狗儿"};
System.out.println(String.join("->", Arrays.asList(strings)));
}
输出:
a,b,c,d
我->爱->小->二->狗儿