一、字符串不可变性
String对象是不可变的。它其实是由字符数组构成
private final char value[];
String类的操作实质都是创建了一个全新的String对象。
二、"+"操作符 重载 与 StringBuilder
1."+"操作符
"+"和"+="是Java中仅有的俩个可以重载的操作符
它适用于简单的字符串拼接,如:
public class TestStringWithOperation {
public static void main(String[] args) {
String str1 = "apple ";
String str2 = str1 + "is my " + "favourite " + "fruit.";
System.out.println(str2);
}
}
这种方式拼接字符串会产生一大堆需要垃圾回收的对象,如果在复杂条件下拼接字符串很影响性能。
2.StringBuilder对象拼接字符串
StringBuilder是Java SE5后引入的,之前使用的都是StringBuffer(线程安全),因此StringBuilder的效率更高
相关方法
方法名 | 功能 |
public StringBuilder insert(int off, int i) | 将 |
public StringBuilder replace(int start,int end,String str) | 使用给定 |
public StringBuilder reverse() | 将此字符序列用其反转形式取代 |
public StringBuilder append(String s) | 将指定的字符串追加到此字符序列 |
String toString() | 返回此序列中数据的字符串表示形式 |
public StringBuilder delete(int start,int end) | 移除此序列的子字符串中的字符 |
StringBuilder类常用来在复杂环境下拼接字符串
public class TestString {
public static void main(String[] args) {
Random random = new Random();
StringBuilder str = new StringBuilder("[");
for (int i = 0; i < 20; i++) {
str.append(random.nextInt(100));
str.append(",");
}
str.delete(str.length()-2,str.length());
str.append("]");
System.out.println(str);
}
}
我们在循环外面先创建StringBuilder对象,而非在循环体内,可以减少其创建的次数
注意:如果可以预估最终字符串的长度,我们可以预先为StringBuilder对象设置大小,避免多次重新分配缓冲
StringBuilder str = new StringBuilder(50);
三、无意识的递归
当我们为某个类重写了Object类的toString方法时,在该类被加入到容器类并且需要打印时,可能会出现递归调用toString()方法
public class InfiniteRecursion {
@Override
public String toString() {
return " InfiniteRecursion address: " + this + "\n";
}
public static void main(String[] args) {
List<InfiniteRecursion> v = new ArrayList<>();
for (int i = 0; i < 10; i++) {
v.add(new InfiniteRecursion());
}
System.out.println(v);
}
}
结果:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at com.test.InfiniteRecursion.toString(InfiniteRecursion.java:14)
...
InfiniteRecursion类继承自根类Object类,并且重写了toString()方法。由于String对象后跟着"+"操作符,所以编译器自动将this强转成了String类型,即this调用了InfiniteRecursion类的toString()方法发生了嵌套调用。
return " InfiniteRecursion address: " + this + "\n";
如果我们需要打印该类的地址,可以直接调用Object类的toString()方法
public class InfiniteRecursion {
@Override
public String toString() {
return " InfiniteRecursion address: " + super.toString() + "\n";
}
public static void main(String[] args) {
List<InfiniteRecursion> v = new ArrayList<>();
for (int i = 0; i < 10; i++) {
v.add(new InfiniteRecursion());
}
System.out.println(v);
}
}
结果:
[ InfiniteRecursion address: com.test.InfiniteRecursion@6d6f6e28
, InfiniteRecursion address: com.test.InfiniteRecursion@135fbaa4
, InfiniteRecursion address: com.test.InfiniteRecursion@45ee12a7
, InfiniteRecursion address: com.test.InfiniteRecursion@330bedb4
, InfiniteRecursion address: com.test.InfiniteRecursion@2503dbd3
, InfiniteRecursion address: com.test.InfiniteRecursion@4b67cf4d
, InfiniteRecursion address: com.test.InfiniteRecursion@7ea987ac
, InfiniteRecursion address: com.test.InfiniteRecursion@12a3a380
, InfiniteRecursion address: com.test.InfiniteRecursion@29453f44
, InfiniteRecursion address: com.test.InfiniteRecursion@5cad8086
]
四、String类的基本方法
String类的基本方法
方法 | 参数,重载版本 | 应用 |
length() | String中的字符个数 | |
charAt() | Int索引 | 取得String中该索引位置上的char |
toCharArray() | 生成一个char[],包含String的所有字符 | |
equalsIgnoreCase() | 与之比较的String | 忽略大小写比较俩个String的内容是否相同,相同返回true |
substring() | 重载版本:起始索引;起始索引+终点索引 | 返回一个新的String,包含参数指定的字符串 |
replace() | 要替换的字符串,用来进行替换的新字符串 | 返回替换后的新字符串 |
toLowerCase(),toUpperCase() | 将字符的大小写改变后,返回一个新的字符串 | |
trim() | 将String俩端的空白符删除,返回一个新的字符串 | |
intern() | 为每个唯一的字符序列仅生成一个String引用 |