String/StringBuilder/StringBuffer的区别
可变性
String 类中使用final关键字修饰字符数组来保存字符串。private final char value[] ,所以String对象是不可变的。
StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类。
在 AbstractStringBuilder 中也是使用字符数组保存字符串 char[] value ,但是没有用final关键字修饰,所以这两个对象是可变的。
线程安全性
String 中的对象是不可变的,也可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基础操作,比如 expandCapacity 、 append 、 insert 、 indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
性能
每次对 String 类型进行改变的时候,都会生成一个新的String对象,然后指针指向新的String对象。StringBuffer 每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。
相同情况下, StringBuilder 相比使用 StringBuffer 仅能获得10%~15%左右的性能提升,但却要冒着多线程不安全的风险。
总结
1、操作少量的数据,适用 String
2、单线程操作字符串缓冲区下操作大量数据:使用 StringBuilder
3、多线程操作字符串缓冲区下操作大量数据:使用 StringBuffer
String info = new String("xyz"); 创建了多少String对象?
两个。
一个是字面量的 xyz 存放在字符串常量池(1.7后移到堆内存里,原先是在方法区)里,一个是通过 new String() 创建的存放在堆内存当中。
解释:Java为了避免产生大量的String 对象,设计了一个字符串常量池。工作原理是,当创建一个字符串时,JVM首先会检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,若没有,则创建,然后放到字符串常量池里,并返回新创建的字符串的引用地址。new String() ,是会在堆内存(不是在字符串常量池)上创建一个新的String对象。
所以, new String('xyz') ,是现在字符串常量池里查找是否有 xyz 的字符串,如果有,则直接引用,如果没有,就创建,然后放在常量池中。当new String时,就会在堆内存中创建一个新的String对象,存储 xyz ,并将内存上的String对象引用地址返回。
扩展:
public class test1 {public static void main(String[] args) {String a = new String("ab"); // a 为一个引用String b = new String("ab"); // b为另一个引用,对象的内容一样String aa = "ab"; // 放在常量池中String bb = "ab"; // 从常量池中查找if (aa == bb) // trueSystem.out.println("aa==bb");if (a == b) // false,非同一对象System.out.println("a==b");if (a.equals(b)) // trueSystem.out.println("aEQb");if (42 == 42.0) { // trueSystem.out.println("true");}}}
