字符串操作是计算机程序设计中最常见的行为,尤其是在Web系统中。
String对象不可变(String对象具有只读特性),故可以给一个String对象加任意个别名,故指向它的引用都不能改变它的值。因此,也不会对其他引用造成影响。String类中每一个会修改String值的方法,实际上都是创建了一个新的String对象来包含修改后的字符串内容,而最初的String对象未做改动。
public class TestStringDemo {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "world";
String str3 = "helloworld";
String str4 = new String("hello");
String str5 = new String("hello").intern();
//intern()返回常量字符串在常量池中的引用,如果有该字符串返回引用,没有则自动生成
System.out.println(str1 == str2);
System.out.println(str2 == str3);
System.out.println((str1 + str2) == str3);
System.out.println("hello"+"world" == str3);
System.out.println(str1 == str4);
System.out.println(str1.equals(str4));
System.out.println(str1 == str5);
}
运行结果:
传参时,实际传递的是引用的一个拷贝。即:每当把String对象作为方法的参数时,都会复制一份引用,而该引用所指的对象其实一直待在原位置从未进行过任何操作。
★参数是为方法提供信息的而不是想让方法改变自己的。
重载:一个操作符在应用于特定的类时,被赋予了特殊的意义。注:用于String的 “+” 与 “+=” 是Java中仅有的两个重载过的操作符,而Java不允许程序员重载任何操作符。
StringBuilder的拼接使用的是append方法,不会产生新的对象(方法中都有return this)
源码:
public class Concatenation {
public static void main(String[] args) {
String str1 = "Xing";
String s = "Sun" + str1 + "Zhe";
System.out.println(s);
}
}
运行结果:
进行反汇编查看代码的工作情况:
从图中我们可以看到编译器自动引入了java.lang.StringBuilder类,并创建了一个StringBuilder对象,用以构造最终的String;而且编译器为每个字符串调用了依次StringBuilder的append()方法,总计3次;最终调用toString()生成结果。
public class TestString_Practice {
public static String implicit(String []str) {
String result = "";
for (int i = 0; i < str.length; i++) {
result += str[i];
}
return result;
}
public static void main(String[] args) {
String [] str = {"a","b","c","d","e","f"};
System.out.println(implicit(str));
}
}
运行结果:
反汇编:
从图中我们可以看到从第8行到第35行构成了一个循环体。StringBuilder是在循环之内构造的,这就意味着每经过一次循环,就会创建一个新的StringBuilder对象。
public class TestString_Practice {
public static String explicit(String [] str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length; i++) {
result.append(str[i]);
}
return result.toString();
}
public static void main(String[] args) {
String [] str = {"a","b","c","d","e","f"};
System.out.println(explicit(str));
}
}
运行结果:
反汇编:
从图中我们可以看到从第13行到第27行构成了一个循环体。StringBuilder是在循环外构造的,这就不会造成内存的浪费。
因此,在为一个类编写toString()方法时,如果字符串操作比较简单,那么编译器就会合理的构造最终的字符串结果。但是,如果要在toString()方法中使用循环,那么最好自己创建一个StringBuilder对象来构造最终的结果。