在遇到字符串常量之间的拼接时,编译器会作出优化,即在编译期间就会完成字符串的拼接。所以,在使用==进行String对象之间的比较时,咱们须要特别注意java
//编译器作了优化,直接在编译的时候将字符串进行拼接 String str1 = "hello" + " java";//至关于str1 = "hello java"; String str2 = "hello java"; System.out.println(str1 == str2);//true String str3 = "hello"; String str4 = " java"; //编译的时候不知道变量中存储的是什么,因此没办法在编译的时候优化 String str5 = str3 + str4; System.out.println(str2 == str5);//false }
String使用的陷阱
String一经初始化后,就不会再改变其内容了。对String字符串的操做其实是对其副本(原始拷贝)的操做,原来的字符串一点都没有改变。好比:
String s ="a"; 建立了一个字符串
s = s+"b"; 实际上原来的"a"字符串对象已经丢弃了,如今又产生了另外一个字符串s+"b"(也就是"ab")。 若是屡次执行这些改变串内容的操做,会致使大量副本字符串对象存留在内存中,下降效率。若是这样的操做放到循环中,会极大影响程序的时间和空间性能,甚至会形成服务器的崩溃。
相反,StringBuilder和StringBuffer类是对原字符串自己操做的,能够对字符串进行修改而不产生副本拷贝或者产生少许的副本。所以能够在循环中使用。服务器
public class strspeed { public static void main(String[] args) { /**使用String进行字符串的拼接*/ String str0 = ""; //本质上使用StringBuilder拼接, 可是每次循环都会生成一个StringBuilder对象 long num1 = Runtime.getRuntime().freeMemory();//获取系统剩余内存空间 long time1 = System.currentTimeMillis();//获取系统的当前时间 for (int i = 0; i < 10000; i++) { str0 = str0 + i;//至关于产生了10000个对象 } long num2 = Runtime.getRuntime().freeMemory(); long time2 = System.currentTimeMillis(); System.out.println("String占用内存 : " + (num1 - num2)); System.out.println("String占用时间 : " + (time2 - time1)); /**使用StringBuilder进行字符串的拼接*/ StringBuilder sb1 = new StringBuilder(""); long num3 = Runtime.getRuntime().freeMemory(); long time3 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { sb1.append(i); } long num4 = Runtime.getRuntime().freeMemory(); long time4 = System.currentTimeMillis(); System.out.println("StringBuilder占用内存 : " + (num3 - num4)); System.out.println("StringBuilder占用时间 : " + (time4 - time3)); } } /* String占用内存 : 24643552 String占用时间 : 134 StringBuilder占用内存 : 0 StringBuilder占用时间 : 1 */