Java 突击 —— 字符串
1 概述
字符串是常用的数据类型。在 Java 中,常见的字符串类型包括 String
、StringBuffer
和 StringBuilder
。
2 String
从 String
的源码可以看到,String
使用数组存储字符串的内容,数组使用关键词 final
修饰,因此数组内容不可变,使用 String
定义的字符串的值也是不可变的。
由于 String
类型的值不可变,因此每次对 String
的修改操作都会创建新的 String
对象,导致效率低下且占用大量内存空间。
3 StringBuffer 和 StringBuilder
StringBuffer
和 StringBuilder
都是 AbstractStringBuilder
的子类,同样使用数组存储字符串的内容,由于数组没有使用关键词 final
修饰,因此数组内容可变,StringBuffer
和 StringBuilder
都是可变类型,可以对字符串的内容进行修改,且不会因为修改而创建新的对象。
在需要经常对字符串的内容进行修改的情况下,应使用 StringBuffer
或 StringBuilder
,在时间和空间方面都显著优于 String
。
StringBuffer
和 StringBuilder
有哪些区别呢?从源码可以看到,StringBuffer
对定义的方法或者调用的方法使用了关键词 synchronized
修饰,而 StringBuilder
的方法没有使用关键词 synchronized
修饰。由于 StringBuffer
对方法加了同步锁,因此其效率略低于 StringBuilder
,但是在多线程的环境下,StringBuilder
不能保证线程安全,因此 StringBuffer
是更优的选择。
4 总结
-
String
是不可变类型,每次对String
的修改操作都会创建新的String
对象,导致效率低下且占用大量内存空间,因此String
适用于字符串常量的情形,不适合需要对字符串进行大量修改的情形。 -
StringBuffer
是可变类型,可以修改字符串的内容且不会创建新的对象,且StringBuffer
是线程安全的,适用于多线程环境。 -
StringBuilder
是可变类型,与StringBuffer
相似,在单线程环境下StringBuilder
的效率略高于StringBuffer
,但是在多线程环境下StringBuilder
不保证线程安全,因此StringBuilder
不适合多线程环境。
5 问题
String
类型的值是否可变?对String
类型的值进行修改操作是否修改了String
的内容?
- 由于
String
的源码中,存储字符串内容的数组使用关键词final
修饰,因此String
类型的值不可变。对String
类型的值进行修改,没有修改String
的内容,而是创建了新的String
对象。
StringBuffer
和StringBuilder
哪一种类型的效率更高?两种类型分别适用于什么样的场合?
StringBuilder
的效率更高,因为StringBuffer
对方法加了同步锁,而StringBuilder
没有对方法加同步锁。虽然StringBuilder
的效率更高,但是因为没有对方法加同步锁,因此在多线程环境下不保证线程安全,只适合单线程环境,而StringBuffer
可以用于多线程环境。