m!String对象的不变性可以保证不会出现别名问题!这是String对象与普通对象的一点区别。
乍看起来这是底层的机制,对我们编程没什么影响。而且这种机制会大幅度提高String的效率,实际上却不是这样。为连接n个字符串使用字符串连接操作时,要消耗的时间是n的平方级!因为每两个字符串连接,它们的内容都要被复制。因此在处理大量的字符串连接时,而且要求性能时,我们不要用String,StringBuffer是更好的选择。
8、StringBuffer类。StringBuffer类是可变的,不会在字符串常量池中,而是在堆中,不会留下一大堆无用的对象。而且它可将字符串缓冲区安全地用于多个线程。每个StringBuffer对象都有一定的容量。只要StringBuffer对象所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。这个固定的容量是16个字符。我给这种算法起个名字叫“添饭算法”。先给你一满碗饭,不够了再给你一满碗饭。
例子:
StringBuffer sb = new StringBuffer(); //初始容量为 16 个字符
sb.append("1234"); //这是4个字符,那么16个字符的容量就足够了,没有溢出
System.out.println(sb.length()); //输出字符串长度是4
System.out.println(sb.capacity()); //输出该字符串缓冲区的容量是16
sb.append("12345678901234567"); //这是17个字符,16个字符的容量不够了,扩容为17+16个字符的容量
System.out.println(sb.length()); //输出字符串长度是17
System.out.println(sb.capacity()); //输出该字符串缓冲区的容量是34
sb.append
("890").reverse().insert(10,"-");
System.out.println(sb); //输出0987654321-09876543214321
字符串的长度和字符缓冲区的容量是两个概念,注意区别。
还有串联的方式看起来是不是很酷!用返回值连接起来可以实现这种简洁和优雅。
10、StringBuilder类。 从J2SE 5.0 提供了StringBuilder类,它和StringBuffer类是孪生兄弟,很像。它存在的价值在于:对字符串操作的效率更高。不足的是线程安全无法保证,不保证同步。那么两者性能到底差多少呢?很多!
请参阅:book.csdn.net/bookfiles/135/1001354628.shtml
实践:
单个线程的时候使用StringBuilder类,以提高效率,而且它的API和StringBuffer兼容,不需要额外的
学习成本,物美价廉。多线程时使用StringBuffer,以保证安全。
11、字符串的比较。
下面这条可能会让你晕,所以你可以选择看或者不看。它不会对你的职业生涯造成任何影响。而且谨记一条,比较字符串要用equals()就ok了!一旦用了“==”就会出现很怪异的现象。之所以把这部分放在最后,是想节省大家的时间,因为这条又臭又长。推荐三种人:一、没事闲着型。二、想深入地理解Java的字符串,即使明明知道学了也没用。三、和我一样爱好研究“茴”字有几种写法。
还是那句老话,String太特殊了,以至于某些规则对String不起作用。个人感觉这种特殊性并不好。看例子:
例子A:
String str1 = "java";
String str2 = "java";
System.out.print(str1==str2);
地球上有点Java基础的人都知道会输出false,因为==比较的是引用,equals比较的是内容。不是我忽悠大家,你们可以在自己的机子上运行一下,结果是true!原因很简单,String对象被放进常量池里了,再次出现“java”字符串的时候,JVM很兴奋地把str2的引用也指向了“java”对象,它认为自己节省了内存开销。不难理解吧 呵呵
例子B:
String str1 = new String("java");
String str2 = new String("java");
System.out.print(str1==str2);
看过上例的都学聪明了,这次肯定会输出true!很不幸,JVM并没有这么做,结果是false。原因很简单,例子A中那