面试题:Java8中String、StringBuilder、StringBuffer的区别
2022/6/30 1:50:28
本文主要是介绍面试题:Java8中String、StringBuilder、StringBuffer的区别,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前置知识
字符串创建问题
- 常量字符串直接赋值
String str = "hello";
- 当使用字符串常量创建一个字符串时,JVM 首先在字符串常量池中寻找具有相同值的字符串,如果找到了它将返回字符串常量池中的字符串对象的引用。否则它会在字符串常量池中创建字符串对象并返回引用
- 使用
new
运算法创建String str = new String("hello");
-
在字符串常量池中查找是否有 "hello" 对象
- 有则返回对应的引用实例
-
没有则创建对应的实例对象
-
在堆中 new 一个 String("hello") 对象
- 创建 str 引用,并将 String("hello") 对象地址赋值给 str
-
- 使用运算符
+
拼接字符串- 字符串常量 + 字符串常量
String str = "hello"+" world";
编译器会直接优化成 "hello world"
- 字符串变量 + 字符串常量
String str = new String("hello") + "world";
变量加常量会new一个StringBuilder并且调用StringBuilder.appen()方法将他们拼接在一起,通过toString()方法返回字符串
- 字符串常量 + 字符串常量
可变性
String
String部分源码如下
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 ............ }
从String源码中可以得知,String类使用了 final
修饰类,意为最终类,同时使用了 final
来修饰的字符数组来保存字符串的,一旦String对象被赋予初始值后不可改变。所以 String 对象是不可变的
StringBuilder 与 StringBuffer
StringBuilder部分源码如下
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ public StringBuilder() { //调用父类构造方法 super(16); } public StringBuilder(int capacity) { //调用父类构造方法 super(capacity); } ......... }
StringBuffer部分源码如下
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { /** * A cache of the last value returned by toString. Cleared whenever the StringBuffer is modified. */ private transient char[] toStringCache; public StringBuffer() { //调用父类构造方法 super(16); } public StringBuffer(int capacity) { //调用父类构造方法 super(capacity); } ........... }
从StringBuilder和StringBuffer源码可以知道,都继承同一个抽象类 AbstractStringBuilder
。而StringBuilder和StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder
实现的。在AbstractStringBuilder
构造方法中可知,使用了字符数组来保存字符串,但是没有使用 final
来修饰字符数组,所以StringBuilder和StringBuffer是可变的
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char[] value; int count; AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; } ............ }
线程安全性
String
由于String对象是不可变的,可以理解为常量,所以String是线程安全的
StringBuilder和StringBuffer
由于StringBuilder和StringBuffer都继承了AbstractStringBuilder,在AbstractStringBuilder中定义很多操作字符串的功能函数,同时StringBuilder和StringBuffer基本都对这些功能函数进行的重写。在StringBuffer重写的方法都加上了 synchronized
同步锁,所以StringBuffer是线程安全的,而StringBuilder重写的方法中并没有加入 synchronized
同步锁标志,所以是线程不安全的。例子 append(String str)方法
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { @Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; } ........... }
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ @Override public StringBuilder append(String str) { super.append(str); return this; } ......... }
性能问题
由于String是不可变的对象,所以在每次对String类型进行改变时,都会生成一个新的String对象,然后将引用指向新的String对象。因此经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别是当内存中无引用的对象多了,对JVM的GC压力很大
使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得 少许性能提升,但多线程不安全
总结
-
操作少量的数据:
String
-
单线程操作字符串缓冲区下操作大量数据:
StringBuilder
-
多线程操作字符串缓冲区下操作大量数据:
StringBuffer
这篇关于面试题:Java8中String、StringBuilder、StringBuffer的区别的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南