1.1 可变性:String是字符串常量,是不可变的。
原因:String对象是由final关键字修饰
初学Java的同学可能会说String是可以重新赋值的啊,我猜你们说的就是以下的方式:
public static void main(String[] args) {
String name = "王大锤";
System.out.println("第一次输出:"+name);
name = "李四";
System.out.println("第二次输出:"+name);
}
两次结果确实是不一样了,但是这并不意味着String的值改变了,而是代表着你重新定义了一个String对象,我们通过输出name的哈希值就可以看一下我们的name对象是不是没有变更过了:
public static void main(String[] args) {
String name = "王大锤";
System.out.println("第一次输出:"+name+"-----哈希值:"+name.hashCode());
name = "李四";
System.out.println("第二次输出:"+name+"-----哈希值:"+name.hashCode());
}
看,name的哈希值在重新赋值之后改变了,所以说我们用的已经不是一开始的那个对象了,而是重新new了一个String对象,里面存的是李四这个值。这里涉及到字符串常量池,以后我会写一篇关于字符串常量池的博文,和大家一下。
所以,既然知道了String是不可变的,那以后再使用for循环对一个字符串频繁的进行操作时,还是不要使用String了,因为在循环里每修改一次String就会产生一个对象,也会开辟一部分空间,而当对象数量达到一定程度的时候,就会启动JVM的垃圾回收机制,而启动垃圾回收机制是比较消耗性能的,所以为了性能考虑还是不要这样使用String。
1.2 安全性 String是线程安全的
原因:String被final关键字修饰,因为其不可变,所以也就是线程安全的
2.1 可变性:StringBuilder是可变的,可以通过append()的方法对字符串进行操作。
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("王");
System.out.println("第一次输出:"+stringBuffer.toString()+"-----哈希值:"+stringBuffer.hashCode());
stringBuffer.append("大锤");
System.out.println("第二次输出:"+stringBuffer.toString()+"-----哈希值:"+stringBuffer.hashCode());
}
Look,我们在使用append方法改变StringBuffer的值后,StirngBuffer的哈希值并没有被改变,这与String有着很明显的区别,所以在很大一部分程度上,StringBuffer弥补了String不可变的缺陷,当我们需要频繁操作字符串时,就可以使用StringBuffer来替代String。
2.2 安全性:StringBuffer是线程安全的
原因:如下图所示,在StringBuffer里,方法都是由synchronized关键字修饰,所以就保证了StringBuffer的线程安全性
StringBuilder是JDK1.5之后推出的StringBuffer低配版,基本功能一致,主要是去掉了StringBuffer方法中的synchronized关键字,这是因为虽然StringBuffer是线程安全的,但是实现的代价是比较大的,所以在很多不会有多线程并发的情况下我们并不需要考虑它的线程安全性,于是乎就有了StringBuilder。
3.1 可变性:同StringBuffer一样 ,StringBuilder是可变的,可以通过append()的方法来添加字符串。
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("王");
System.out.println("第一次输出:"+stringBuilder.toString()+"-----哈希值:"+stringBuilder.hashCode());
stringBuilder.append("大锤");
System.out.println("第二次输出:"+stringBuilder.toString()+"-----哈希值:"+stringBuilder.hashCode());
}
输出结果:
3.2 安全性:StringBuilder线程不安全的
因为StringBuilder是StringBuffer的低配版,去掉了synchronized关键字,所以StringBuilder是线程不安全的
在综合了以上String,StringBuffer,StringBuilder的特性后,我们可以得出以下结论:
1.在我们不需要频繁对字符串进行改动或者不需要改动的情况下,推荐使用String;
2.当我们需要频繁对字符串进行改变,而且不需要考虑线程安全的情况下,推荐使用StringBuilder;
2.当我们需要频繁对字符串进行改变,需要考虑线程安全的情况下,推荐使用StringBuffer;