Java String、StringBuffer和StringBuilder的区别

简介: 1.String类字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。String对象实现了Serializable接口,说明String对象可以串行化(在网络中进行传输),同时实现了Comparable接口,说明String对象可以进行比较🎁


1.String类


字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。


String对象实现了Serializable接口,说明String对象可以串行化(在网络中进行传输),同时实现了Comparable接口,说明String对象可以进行比较🎁


String是个final类,这代表它是不可被继承的


String的本质依然是char数组(或者byte数组,要看JDK的版本),通过源码我们可以轻松的得知:


// JDK1.9及之后的版本,String的字符串内容保存在一个叫做value的byte数组中
@Stable
private final byte[] value;
// 注意这里的value数组是一个final类型,这代表它是不可以被修改的,这里指的是value的地址不能发生修改,而并非value数组里的值


总结:jdk1.8及以前String使用的是char数组,jdk1.9及以后使用的是byte数组。🎈


为什么改成byte数组了呢?🙌


因为开发人员发现人们使用的字符串值是拉丁字符居多而之前使用的char数组每一个char占用两个字节而拉丁字符只需要一个字节就可以存储,剩下的一个字节就浪费了,造成内存的浪费,gc的更加频繁。因此在jdk9中将String底层的实现改为了byte数组。


2.StringBuffer


概述


当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。


和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。这极大的节省了资源的使用


StringBuffer的本质依然是char数组(或者byte数组,要看JDK的版本)但是和String不同的是,该数组不是final类型的🎈和String类一样,StringBuffer类也是final类型,代表它不能被继承!🤷‍♂️


String VS StringBuffer


String是不可变的对象,因此每次在对String类进行改变的时候都会生成一个新的String对象,然后将指针指向新的String对象,所以经常要改变字符串长度的话不要使用String,因为每次生成对象都会对系统性能产生影响,特别是当内存中引用的对象多了以后,JVM的GC就会开始工作,性能就会降低


使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用,所以多数情况下推荐使用StringBuffer,特别是字符串对象经常要改变的情况


String对象的速度并不会比StringBuffer对象慢的情况:


String s1 = "This is only a" + " simple" + " test";
StringBuilder sb = new StringBuilder("This is only a").append(" simple").append(" test");


生成 String s1对象的速度并不比 StringBuffer 的 sb慢。其实在Java Compiler里,自动做了如下转换:


String s2 = "This is only a";
String s3 = " simple";
String s4 = " test";
String s1 = s2 + s3 + s4;


这时候,Java Compiler会规规矩矩的按照原来的方式去做,String的 + 操作利用了StringBuilder(或StringBuffer)的append方法实现


StringBuffer三种构造器初始化


// 创建一个大小为16的char[] 数组,用于存放字符内容
StringBuffer stringBuffer = new StringBuffer();
// 指定char[]容量大小
StringBuffer stringBuffer1 = new StringBuffer(100);
// 通过给一个string创建stringbuffer,初始容量为字符串长度 + 16
StringBuffer dahezhiquan = new StringBuffer("dahezhiquan");


String和StringBuffer的转换


String --> StringBuffer😀


// String --> StringBuffer
String str = "hello";
// 方法一:通过构造器
StringBuffer stringBuffer2 = new StringBuffer(str);
// 方法二:通过append
StringBuffer stringBuffer3 = new StringBuffer();
stringBuffer3.append(str);


StringBuffer --> String😁


// StringBuffer --> String
StringBuffer stringBuffer4 = new StringBuffer("lsp");
// 方法一:通过toString方法
String s = stringBuffer4.toString();
// 方法二:使用构造器
String s1 = new String(stringBuffer4


3.StringBuilder


概述


一个可变的字符序列,此类提供一个与StringBuffer兼容的API,但不保证同步(不是线程安全的),用在字符串缓冲区被单个线程使用的时候,如果可能建议优先使用该类,因为在大多数的时候,它比StringBuffer要快


StringBuilder类是final类型,不能被继承!StringBuilder的本质依然是char数组(或者byte数组,要看JDK的版本),该数组不是final类型🎈


常用API


StringBuilder append(String str):


添加一部分内容


StringBuilder stringBuilder = new StringBuilder("wode");
stringBuilder.append("shijie");
System.out.println(stringBuilder);  // wodeshijie


void setCharAt(int i, char c):

将第i个代码单元设置为c


StringBuilder stringBuilder = new StringBuilder("wode");
stringBuilder.setCharAt(0, 't');
System.out.println(stringBuilder);  // tode


StringBuilder insert(int offset, String str):

在offset位置插入一个字符串


StringBuilder stringBuilder = new StringBuilder("wode");
stringBuilder.insert(1, "dada");
System.out.println(stringBuilder);  // wdadaode


StringBuilder delete(int startIndex, int endIndex):

删除偏移量从startIndex到-endIndex-1的代码单元


StringBuilder stringBuilder = new StringBuilder("wodeshijie");
stringBuilder.delete(1, 3);
System.out.println(stringBuilder);  // weshijie


4.总结


如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer

不要使用String类的”+”来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则

相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer

去留无意,闲看庭前花开花落;宠辱不惊,漫随天外云卷云舒。🥞


目录
相关文章
|
2月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
198 14
|
3月前
|
存储 安全 Java
String StringBuffer StringBuilder 区别详解与对比分析
本文详细解析了Java中String、StringBuffer和StringBuilder的区别,从可变性、线程安全性和性能三个方面进行对比,并结合具体应用场景分析了三者的适用范围。通过性能测试示例展示了它们在字符串拼接时的效率差异,同时提供了实际代码案例帮助理解。总结指出,String适合少量操作或线程安全场景,StringBuffer适用于多线程环境,而StringBuilder则在单线程下性能最优。开发者应根据需求选择合适的类以优化程序性能。文末还附有相关面试资料供参考。
610 2
|
3月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
77 0
|
6月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
141 11
|
6月前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、"+"操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
148 9
|
6月前
|
存储 JavaScript Java
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化
|
10月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
292 2
|
11月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
219 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性

热门文章

最新文章