String
我们都知道String是一个不可变类型,那么为什么String是不可变的呢,通过阅读源码发现:
private final char value[];
String的底层是一个用final修饰的一个数组,所以它是一个不可变的类型。
String类型的定义:
String类型的创建,会在字符串常量池中查找是否有这个字符串,如果有则直接将地址赋给引用,如果没有则会在堆上进行创建。
字符串的拼接:
String string="abc";
string= string+"def";
实际上,原来string的内容是不变的,只是string由原来指向“abc"内存地址转为指向了“abcdef”内存地址而已,也就是说多开辟了一块内存地址给“abcdef"字符串。因此,在用加号将String类型的字符串进行拼接的时候,往往我们只是想要得到最后一个结果,但是在这个过程中会产生很多对象,因为每使用一次加号进行拼接就会产生一个新的对象。这样就会对内存空间造成很大的浪费。
StringBuilder
阅读StringBuilder的源码不难发现,StringBuilder的几个构造方法,基本上都调用了父类的构造方法(StringBuilder(CharSequence seq)内部调用了StringBuilder(int capacity),而这个构造方法内部也调用了父类的构造方法)。查看父类的源码:
因此,StringBuilder是可变的。
因为StringBuilder是可变的,所以每次对StringBuilder对象进行修改,不会产生新的对象。同时,由于StringBuilder没有实现线程安全的功能,所以StringBuilder的执行效率要高于StringBuffer。
StringBuffer
StringBuffer的几个构造方法与StringBuilder相同,因此它也是可变的。
StringBuffer同时还实现了线程安全:
StringBuffer的方法中都添加了synchronized关键字,都加上了一把锁,用来实现线程安全。
在多线程开发的情况下为了保证线程安全,一般使用StringBuffer,在单线程情况下因为不用考虑线程安全,所以使用StringBuilder,因为StringBuilder没有加锁,所以效率稍微高于StringBuffer。