首页 > 其他分享 >面试官:请聊一聊String、StringBuilder、StringBuffer三者的区别

面试官:请聊一聊String、StringBuilder、StringBuffer三者的区别

时间:2024-01-18 09:05:23浏览次数:31  
标签:面试官 String 一聊 StringBuilder StringBuffer 字符串 final append

面试官:“小伙子,在日常的写代码过程中,使用过String,StringBuilder和StringBuffer没?”
我:“用过的呀!”
面试官:“那你就来聊一聊,他们之间有什么区别,不同场景下如何选择吧”
我:“好嘞!”
在Java的开发过程中,使用频率最高的就是String字符串,但由于在字符串存储和拼接的过程中,涉及到很多场景需要因地制宜的选用StringBuider与StringBuffer。
我们先来聊一聊String,由源码引入话题:
Java8中的String源码

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
  //...
}

我们从源码中可以总结出如下几点内容:

  1. String类被final关键字修饰,意味着它不可被继承;
  2. String的底层采用了final修饰的char数组,意味着它的不可变性;
  3. 实现了Serializable接口意味着它支持序列化;
  4. 实现了Comparable接口,意味着字符串的比较可以采用compareTo()方法,而不是==号,并且Sring类内部也重写了Object的equals()方法用来比较字符串相等。

Java9以后String的底层数据由char类型改为了byte类型,看源码:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
    private final byte coder;
    private int hash;
}

这样做的目的是为了节省字符串占用的内存空间,在大字符串处理中提升效率,同时也降低了垃圾回收的次数,提升性能。
面试官:“String类设置为不可变对象的话,岂不是每次创建或者字符串拼接的时候都会创建对象,增加开销?那为什么还要用final修饰呢?”
我:“嗯~这个问题非常好呀,我理解的是两个原因”

1、String 类是最常用的类之一,为了效率,禁止被继承和重写
2、为了安全。String 类中有很多调用底层的本地方法,调用了操作系统的API,
如果方法可以重写,可能被植入恶意代码,破坏程序。其实Java 的安全性在这里就有一定的体现啦。

基于以上String的特点,Java官方自然也知道它的弊端,所以为了全场景的最优方案适配,便产生了StringBuilder和StringBuffer这两个String的近亲字符串处理类,他们都实现了CharSequence 接口。
StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串,不过没有使用 final 和 private 关键字修饰,所以可以解决在字符串拼接时的性能问题,最关键的是这个 AbstractStringBuilder 类还提供了很多修改字符串的方法,比如 append 方法。
源码:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value;
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
    //...
}

StringBuilder源码

public final class StringBuilder extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    // ...

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

    // ...
}

StringBuilder替代String的字符串拼接案例

Java 是一门解释型的编程语言,所以当编译器遇到 + 号这个操作符的时候,会将

new String("Hello") + new String("World") 

解释为

new StringBuilder().append("Hello").append("World").toString();

并且在循环字符串拼接的时候,String的“+”拼接方式,会在循环内部多次创建StringBuilder对象,白白浪费了资源,如:

String[] arr = {"he", "llo", "world"};
String s = "";
for (int i = 0; i < arr.length; i++) {
    s += arr[i];
}
System.out.println(s);

这一段代码完全就可以直接使用StringBuilder调用append实现方式来替代:

String[] arr = {"he", "llo", "world"};
StringBuilder s = new StringBuilder();
for (String value : arr) {
    s.append(value);
}
System.out.println(s);

StringBuffer源码

public final class StringBuffer extends AbstractStringBuilder implements Serializable, CharSequence {

    public StringBuffer() {
        super(16);
    }
    
    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }

    public synchronized String toString() {
        return new String(value, 0, count);
    }

    // 其他方法
}

从它的源码我们可以看出,内部的实现与StringBuilder相差无机,无非是在方法的前面加了synchronized 关键字进行了同步,以确保在多线程场景下的线程安全,但在大部分的非多线程场景下,由于同步锁的存在会导致执行效率过低,并且即便在多线程情况下,依旧可以通过ThreadLocal搭配StringBuilder的方式来安全的修改字符串,所以,实际开发中,StringBuilder 的使用频率也是远高于 StringBuffer,甚至可以这么说,StringBuilder 完全取代了 StringBuffer。

三者异同点总结

相同点:
1、都可以储存和操作字符串
2、都使用 final 修饰,不能被继承
3、提供的 API 相似
异同点:
1、String 是只读字符串,String 对象内容是不能被改变的
2、StringBuffer 和 StringBuilder 的字符串对象可以对字符串内容进行修改,在修改后的内存地址不会发生改变
3、StringBuilder 线程不安全;StringBuffer 线程安全

标签:面试官,String,一聊,StringBuilder,StringBuffer,字符串,final,append
From: https://www.cnblogs.com/JavaBuild/p/17971699

相关文章

  • [cpp]: operator""s -- <string>
    [cpp]: operator""s -- <string>    1operator""s:将一个字符数组字面量转化为【basic_string】类型数据。1.1#include<string>1.2operator""s :convertsacharacterarrayliteralto basic_string   2e.g.......
  • 《数据篇》String
    生成UUID下面是一个简单的生成代码:把生成的UUID简单的处理了一下importjava.util.UUID;publicclassUuid{ publicstaticvoidmain(String[]args){ for(inti=0;i<5;i++){ //注意replaceAll前面的是正则表达式 Stringuuid=UUID.randomUUID().toStri......
  • C# String 类在开发中常用到的方法汇总【详细版】
    前言:在开发过程中我们经常用到的string类自带方法就那些个,但是有时突然不记得,又得翻看文档,比较麻烦,自己直接总结下来,方便查看1、String.Contains返回一个值,该值指示指定的字符是否出现在此字符串中。strings1="Thequickbrownfoxjumpsoverthelazydog";strings2=......
  • 聊一聊为什么我要整合Microsoft.Extensions.DependencyInjection和Castle.Core
    前言如果用到动态代理,大家可能会有几种选择,排到前列的是Autofac+Castle、AspectCore和DoraInterception,我将从我当时研究的经历,以及我遇到的场景,为大家展示下聊一聊我为什么要费时费力的整合Microsoft.Extensions.DependencyInjection和Castle.Core当时遇到的场景直接上源码......
  • 面试官:如何保证本地缓存的一致性?
    有人可能看到“本地缓存”这四个字就会觉得不屑,“哼,现在谁还用本地缓存?直接用分布式缓存不就完了嘛”。然而,这就像你有一辆超级豪华的房车一样,虽然它空间很大,设备很全,但你去市中心的时候,依然会开小轿车一样,为啥?好停车啊!所以,不同的缓存类型是有不同得使用场景的。并且,为了防止缓......
  • String.Format格式说明
    String.Format格式说明  C#格式化数值结果表字符说明示例输出C货币string.Format("{0:C3}",2)$2.000D十进制string.Format("{0:D3}",2)002E科学计数法1.20E+0011.20E+001G常规string.Format("{0:G}",2)2N用分号隔开的数字......
  • string 字符串用法C++
    substr() c_str() size()/length()  empty() clear() #include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<vector>usingnamespacestd;intmain(){stringa="abc";......
  • Json Schema介绍 和 .net 下的实践 - 基于Lateapexearlyspeed.Json.Schema - 基础1 -
    本系列旨在介绍JsonSchema的常见用法,以及.net实现库Lateapexearlyspeed.Json.Schema的使用这篇文章将介绍JsonSchema中的type关键字,和string类型的常见验证功能。用例基于.net的LateApexEarlySpeed.Json.Schemanugetpackage。这是新创建的一个JsonSchema在.net下的高性能......
  • C#中substring ()的用法
    String.SubString(int index,int length)  index:开始位置,从0开始   length:你要取的子字符串的长度  示例:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespacestr_sub{classProgram{staticvoidMain(string[]args){strin......
  • 面试官:请谈一谈你对OOP的理解?
    文编|JavaBuild哈喽,大家好呀!我是JavaBuild,以后可以喊我鸟哥!俺滴座右铭是不在沉默中爆发,就在沉默中灭亡,一起加油学习,珍惜现在来之不易的学习时光吧,等工作之后,你就会发现,想学习真的需要挤时间,厚积薄发啦!标题中的问题可以说是很多公司一面的必问题,作为一种划时代的编程思想,OOP(O......