博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
探索String 、StringBuilder 、StringBuffer 的奥妙
阅读量:7071 次
发布时间:2019-06-28

本文共 2769 字,大约阅读时间需要 9 分钟。

Java 平台提供了两种类型的字符串:String 和 StringBuffer/StringBuilder,它们都可以储存和操作字符串,区别如下:

1)String 是只读字符串,也就意味着String引用的字符串内容是不能被改变的。初学者可能会有这样的误解:

1. String str = “abc”;  2. str = “bcd”;复制代码

如上,字符串 str 明明是可以改变的呀!其实不然,str仅仅是一个引用对象,它指向一个字符串对象“abc”。 第二行代码的含义是让str重新指向了一个新的字符串“bcd”对象,而“abc”对象并没有任何改变,只不过该对象已经成为一个不可及对象罢了。

2)StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改。

3)StringBuilder 是Java5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的, 因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比 StringBuffer 要高。

什么情况下用“+”运算符进行字符串连接比调用 StringBuffer/StringBuilder 对象的 append 方法连接字符串性能更好?

字符串是 Java 程序中最常用的数据结构之一。在 Java 中 String 类已经重载了"+"。也就是说,字符串可以直接使用"+"进行连接,如下面代码所示:

1.String s = "abc" + "ddd";复制代码

使用 jad 反编译的好处之一就是可以同时生成字节码和源代码。这样可以进行对照研究。从上面的代码很容易看出,虽然在源程序中使用了"+",但在编译时仍然将"+"转换成 StringBuilder。因此,我们可以得出结论,在 Java 中 无论使用何种方式进行字符串连接,实际上都使用的是 StringBuilder。 那么是不是可以根据这个结论推出使用"+"和 StringBuilder 的效果是一样的呢?这个要从两个方面的解释。如果从运行结果来解释,那么"+"和 StringBuilder是完全等效的。但如果从运行效率和资源消耗方面看,那它们将存在很大的区别。

如果连接字符串行表达式很简单(如上面的顺序结构),那么"+"和StringBuilder 基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的 Java Byte Code 就会有很大的区别。

大家可以看到,虽然编译器将"+"转换成了 StringBuilder,但创建 StringBuilder 对象的位置却在for语句内部。这就意味着每执行一次循环,就会创建一个 StringBuilder对象(对于本例来说,是创建了10个StringBuilder 对象),虽然Java有垃圾回收器,但这个回收器的工作时间是不定的。如果不断产生这样的垃圾,那么仍然会占用大量的资源。解决这个问题的方法就是在程序中直接使用 StringBuilder 来连接字符串。

StringBuffer 和 StringBuilder 的功能基本一样,只是 StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的。因此,StringBuilder 的效率会更高。

class StringEqualTest {   public static void main(String[] args) {    String s1 = "Programming";   String s2 = new String("Programming");    String s3 = "Program";   String s4 = "ming";   String s5 = "Program" + "ming";   String s6 = s3 + s4;   System.out.println(s1 == s2);   System.out.println(s1 == s5);   System.out.println(s1 == s6);   System.out.println(s1 == s6.intern());   System.out.println(s2 == s2.intern());   //false   //true   //false   //true   //false}}复制代码

补充:解答上面的面试题需要知道如下两个知识点:

  1. String 对象的 intern()方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;

  2. 字符串的+操作其本质是创建了 StringBuilder 对象进行 append 操作,然后将拼接后的 StringBuilder 对 象用 toString 方法处理成 String 对象,这一点可以用 javap -c StringEqualTest.class 命令获得 class 文件对应 的 JVM 字节码指令就可以看出来。

String、StringBuffer、StringBuilder 的区别?

(1)、可变不可变 String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串对象。 StringBuffer:在修改时会改变对象自身,每次操作都是对StringBuffer 对象本身进行修改,不是生成新的对象; 使用场景:对字符串经常改变情况下,主要方法:append(),insert()等。

(2)、线程是否安全 String:对象定义后不可变,线程安全。

StringBuffer:是线程安全的(对调用方法加入同步锁),执行效率较慢,适用于多线程下操作字符串缓冲区 大量数据。

StringBuilder:是线程不安全的,适用于单线程下操作字符串缓冲区大量数据。

(3)、共同点

StringBuilder 与 StringBuffer有公共父类AbstractStringBuilder(抽象类)。 StringBuilder、StringBuffer 的方法都会调用 AbstractStringBuilder 中的公共方法,如 super.append(...)。 只是 StringBuffer 会在方法上加 synchronized 关键字,进行同步。最后,如果程序不是多线程的,那么使用 StringBuilder 效率高于 StringBuffer。

转载地址:http://jrell.baihongyu.com/

你可能感兴趣的文章
常用算法Java实现之直接插入排序
查看>>
转载 radio值获取
查看>>
学习SpringMVC——你们要的REST风格的CRUD来了
查看>>
NLPIR数据语义挖掘技术为企业提供精准管理
查看>>
通过本地yum源安装软件报错[Errno 14] PYCURL ERROR 56 - "Failure when receiving data from the peer"...
查看>>
android常用调试工具fiddle、wireshark和android studio的配置
查看>>
Java实现几种常见排序方法
查看>>
NOIP2017 复盘
查看>>
jxa快速入门,Javascript已加入AppleScript全家桶
查看>>
洛谷P3622 动物园
查看>>
Angular Encapsulation - css选择器选不到非angular组件(插件)
查看>>
iOS开发之UIScrollView
查看>>
mysql 使用 insert ignore into和unique实现不插入重复数据功能
查看>>
c++操作符重载_12
查看>>
eclipse 安装反编译工具
查看>>
我的Java开发学习之旅------>Java多线程下载文件 实例
查看>>
WireShark简单使用以及TCP三次握手
查看>>
什么是@guid
查看>>
nodeType的12种类型
查看>>
步步为营 .NET 代码重构学习笔记 十三
查看>>