stringbuilder class再反编译_直击面试:String、StringBuilder 和 StringBuffer 区别详解

b8c9f7ac3fde66c553332c2aa00a3731.png    736513a7c2e57ffab2b42b2b786efeb4.gif  作者|Summer cc59dd3a736c212e5b5da3d273e9e13b.png

为了避免大家出现此类情况,不在基本问题上丢失工作机会,本篇文章我们一起来深入了解一下这三个对象。

String

在Java中字符串不是基本数据类型,而是对象。

Java提供了String类来创建和操作字符串。需要注意的是,String的值是不可变的,因为String对象被final修饰,是不可变的类对象。

ace50081bb9db8f360a37e0e23ecffb9.png

从String的源码中可以看出,String类是一个final类,因此每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。

下面我们看一段代码(代码区域可以左右滑动):

public class TestDemo {    public static void main(String[] args) {        String s1 = "hello";        String s2 = "java" + "python";        String s3 = s1 + "world";        String s4 = new String("hello");    }}

我们看一下这段代码的反编译代码(代码区域可以左右滑动):

  public static void main(java.lang.String[]);    Code:       0: ldc           #2                  // String hello       2: astore_1       3: ldc           #3                  // String javapython       5: astore_2       6: aload_1       7: invokedynamic #4,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;      12: astore_3      13: new           #5                  // class java/lang/String      16: dup      17: ldc           #2                  // String hello      19: invokespecial #6                  // Method java/lang/String."":(Ljava/lang/String;)V      22: astore        4      24: return}

你会发现,每次在操作字符串的时候,jvm都会创建新的对象,摒弃之前的对象,这样就造成了内存大量的浪费。

那么对于下面的代码:

String name="王者荣耀";System.out.println(name);name="吃鸡";System.out.println(name);

很多人会认为,不是说字符串不可变吗?这个name的值怎么变化了呢?其实我们看似变化了,其实jvm内部是这样操作的。

f2577eceff65ab583f34c4e92fbd08e5.png

由此可见,name最终抛弃了“王者荣耀”这个值,最后指向了“吃鸡”,但是“王者荣耀”这个内容还在内存中,会随着下一次垃圾回收给回收掉。可是垃圾回收机制的时机是不可控的,这就造成了在此期间内存的浪费!

再看以下代码:

String str1 = "hello world";String str2 = new String("hello world");String str3 = "hello world";String str4 = new String("hello world");          System.out.println(str1==str2); System.out.println(str1==str3); System.out.println(str2==str4);

输出结果:

falsetruefalse

在上述代码中,String str1 = "hello world";和String str3 = "hello world"; 都在编译期间生成了 字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。

1a5346762ccf73795ba0de1b370a5f44.png

  众所周知,通过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

StringBuffer

 简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

 而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

StringBuffer是线程安全的,所有的方法都加锁,进行资源同步串行化处理,我们可以通过它的源码可以看出:

cf0227ead9b6cd27e2aaf29a8c354b88.png

StringBuilder

StringBuilder是线程不安全的, StringBuilder 类表示一个可变的字符序列,我们知道,StringBuilder 是非线程安全的容器,一般适用于 单线程 场景中的字符串拼接操作。 StringBuilder与StringBuffer继承体系

3172bbac263fce9275bc44f9ac0816a7.png

应用场景

String

在字符串内容不经常发生变化的业务场景优先使用String类例如:常量声明、少量的字符串拼接操作等

StringBuffer

在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程环境下

例如XML解析、HTTP参数解析与封装。

StringBuilder

在频繁进行字符串的运算(如拼接、替换、删除等) ,并且运行在单线程环境下

例如SQL语句拼装、JSON封装等。

三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

好了,今天的内容就到这里,希望各位面试的时候不仅仅是只回答一些片面的东西,你的回答代表着你开发功底的深浅。

e2b670897fc2a2ac5e879faebd2fcc6d.png

往期精彩回顾

5888684545ee992123d8e25a1553aac1.png

编程学不会?这样学,你会成为大牛!

Windows很卡该怎么办?我只说这一次!

我要吹爆它!Windows办公神器软件!!

Java必备软件合集

希望这篇文章可以帮助到你~欢迎大家点个 在看,分享至朋友圈 IT的路上 我 一直陪着你

90ae83b348c29b09362b144156a17f25.png

写留言99+

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值