Java中字符不变性

来源:互联网 发布:windows已出现关键问题 编辑:程序博客网 时间:2024/05/28 17:07

Java字符串不变性与其解决方案

一张图说明问题

String在初始化后事不可变的。
String a = “aaa”;
String a = a +”bbb”;
执行第二条语句时,会分配新的内存用来存放字符串“aaabbb”,a 指向该地址。
String的不变性的机制显然会在String常量内有大量的冗余。
如:”1”+”2”+”3”+…..+”n”产生了n+(n+1)个String对象!因此Java为了更有效地使用内存,JVM流出了一块特殊的内存区域,被称为“String常量池”,如String a = “abc”; 当你定义这样一个变量的时候,Java此时先会去常量池寻找有没有 “abc”这样的字符串,如果有,直接把内存地址交给 a,否则就生成一个 “abc”的字符串当下一个 String b =”abc”;的时候,发现常量池已有 “abc”了,此时JVM不会再次生成”abc”,而是直接交给”abc”引用给b,所以此时你会发现a,b指向同一地址
这里String常量池不是在栈内存也不是堆内存,时一块特殊内存。
String a = “aaa”;//在常量池分配空间
String b = newString(“aaa”); //在堆内存分配空间
因为字符串的不变性,所以建议不要做大量的字符串累加操作,这样效率很低。为了解决这个问题,Java提供了两个类 StringBuffer和 StringBuilder。
StringBuffer类是可变的,不会再字符串常量池中,而是在堆中,不会留下一大堆无用的对象。而且它可将字符串缓冲区安全地用于多个线程。每个StringBuffer对象都有一定的容量。只要StringBuffer对象所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则次容量自动增大。这个固定的容量是16个字符。这种算法名字可以叫“添饭算法”。先给你一满碗饭,不够了再给你一满碗饭。
//居然还有添饭算法,本以为鸵鸟算法就够无厘头的了。。
从 J2SE5.0提供了StringBuilder类,它和StringBuffer类时孪生兄弟,很想,它存在的价值在于:堆字符串操作的效率更高。不足的是线程安全无法保证,不保证同步。

/**这里先是在堆中创建String对象"aaa",然后"aaabbb"覆盖原来的"aaa",如果不用StringBuilder就是创建一个新的"aaabbb"对象**/ StringBuilder sb = newStringBuilder();    sb.append("aaa");    sb.append("bbb");    String result =sb.toString();   System.out.println(result);