首页 > 编程语言 >【后端面经-Java】String与StringBuffer与StringBuilder的比较

【后端面经-Java】String与StringBuffer与StringBuilder的比较

时间:2023-07-24 15:23:26浏览次数:53  
标签:Java String StringBuffer 线程 StringBuilder 字符串

目录

1. String

  1. 不可变
    查看String源码如下:
    public final class String implements java.io.Serializable, Comparable<String>, CharSequence{
        /** The value is used for character storage. */
        private final char value[];
    
        /** The offset is the first index of the storage that is used. */
        private final int offset;
    
        /** The count is the number of characters in the String. */
        private final int count;
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;
        
        ......
    }
    
    由源码可知,String中存储数据的数组被关键字final修饰,因此是不可变的
  2. 运算和操作
    1. 创建对象
      创建对象有两种方式:
      //方式一
        String str = "abc";
      //方式二
        String str = new String("abc");
      
      两种方式都会在栈中创建一个字符串变量str,但它们的内存分配方式是不同的。
      我们可以通过如下代码直观看出两种方式的不同
        String str1 = "abc";
        String str2 = "abc";
        String str3 = new String("abc");
        String str4 = new String("abc");
        System.out.println(str1 == str2); //true
        System.out.println(str3 == str4); //false
      
      为了理解这部分内容,最好先了解一下Java中的内存分配机制,可参考此篇博客:【后端面经-Java】JVM内存分区详解
      总之,简单来说,内存主要分为栈、堆、方法区等部分,栈中存放局部变量,堆中存放对象实例和数组,方法区中存放类信息和常量等,常量池一开始均在方法区中,后来运行时常量池转移到堆中,下文均按照这种内存分配模型来讨论。
      下图展示了两种创建方式下的内存情况:
      • 方式一
      • 在栈中创建一个变量之后,需要指向具体的值,首先会在常量池中查找abc,如果找到,则指向这个字符串,如果没有找到,在运行时常量池中创建这一字符串,然后指向它。
      • 因此,str1str2指向的是同一个字符串,即同一个内存单元,所以str1 == str2true
      • 方式二
        • 在栈中创建一个变量之后,在堆中构造一个新的字符串对象,然后指向它。
        • 因此,str3str4指向的是两个不同的内存单元,所以str3 == str4false
    2. "+"运算
      • 每次"+"运算虽然看似很简便,实际上需要创建一个新的String对象来接收结果,而作为运算数的String对象依然存在于堆中,成为垃圾占用堆空间,需要Java垃圾回收机制进行处理。(关于Java垃圾回收机制,可参考此篇博文:
      • 这种操作是非常低效的,且造成了大量的内存占用,因此在实际开发中,应尽量避免使用"+"运算符来进行字符串拼接,而应该使用StringBufferStringBuilder来进行字符串拼接。
    3. substring() && replace() && concat()
      • 这些操作的一个特点就是:创建新的String对象承接结果,而原来的String对象依然存在于堆中。
  3. 适用场景
    1. 适用于字符串不需修改的场景。

2. StringBuffer

  1. 可变
    1. StringBuffer源代码中数组是可变长度的。
  2. 线程安全
    1. 在类定义过程中,适用synchronized关键字,保证线程安全。
    2. 线程安全与否是StringBufferStringBuilder的重要区别之一。
  3. 运算和操作
    1. append():在字符串末尾添加新字符串;
    2. insert():在指定位置插入新字符串;
    3. toString():将StringBuffer转换为String
  4. 适用场景
    • 多线程,字符串需要频繁修改

3. StringBuilder

  1. 可变
    1. StringBuffer一样,StringBuilder源代码中数组是可变长度的。
  2. 线程不安全
    1. 并没有使用synchronized关键字,因此线程不安全。
    2. 因为线程不安全,不需要考虑线程安全的处理,所以StringBuilder的性能比StringBuffer略高。
  3. 适用场景:
    1. 单线程,字符串需要频繁修改

4. 性能提升

  1. 为了提升性能,避免在字符串需要修改的场景下使用String类;
  2. 在初始定义时预先估计字符串的长度,对StringBuilderStringBuffer进行初始化,避免频繁扩容,提升性能。
     StringBuilder sb = new StringBuilder(100);
     StringBuffer sb = new StringBuffer(100);
    ``
    
    

5. 总结和比较

下图是对三者进行的比较:

面试模拟

Q:简单介绍一下String和StringBuilder的区别
A:首先,String定义的字符串是不可变的,使用拼接函数或者操作符将会创建一个新的String对象,性能不高;而StringBuilder定义的字符串可变,且线程不安全使得其具有较好的性能,在字符串需要频繁修改的场景下,使用StringBuilder会更好。

参考资料

  1. Java String、StringBuffer 和 StringBuilder 的区别
  2. Java中String和StringBuilder的区别
  3. 探秘Java中的String、StringBuilder以及StringBuffer

标签:Java,String,StringBuffer,线程,StringBuilder,字符串
From: https://www.cnblogs.com/CrazyPixel/p/17577322.html

相关文章

  • Java基础--2021Java面试题系列教程--大白话解读
    前言序言再高大上的框架,也需要扎实的基础才能玩转,高频面试问题更是基础中的高频实战要点。适合阅读人群Java学习者和爱好者,有一定工作经验的技术人,准面试官等。阅读建议本教程是系列教程,包含Java基础,JVM,容器,多线程,反射,异常,网络,对象拷贝,JavaWeb,设计模式,Spring-SpringMVC,SpringB......
  • javaScript 小知识
    ??运算符只有前面的值是undefined才会执行letstatus=undefined;lettext=status??"暂无"console.log(text)//暂无?.运算符这在有时候处理对象时非常有用,看下面案例,person.name返回undefined然后在调用toString这时肯定会报错,这时使用?.运算符就不会产生错误,?.......
  • java8 时间相关工具介绍
    System.currentTimeMillis()(java.util包下)Date表示当前日期和时间的日期对象Calendar日历TimeZone该类表示时区偏移量SimpleDateFormat格式化Date,建议使用jdk8后的DateTimeFormatter(java.time包下)TemporalUnit时间单位这个概念,这个是个接口,唯一的实现是枚举类ChronoUnitTemp......
  • 中文同义词库java
    中文同义词库Java在自然语言处理领域,同义词是指在语义上具有相似或相同意义的词语。使用同义词可以帮助我们对文本进行更准确的分析和理解。为了方便开发者进行中文文本处理,我们可以利用中文同义词库来实现同义词替换、文本相似度计算等功能。本文将介绍如何使用Java编程语言来......
  • 怎么找java项目日志输出的路径
    项目方案:Java项目日志输出路径的查找方法背景在Java项目开发过程中,日志是非常重要的一部分,可以帮助开发人员快速定位和解决问题。日志输出路径的查找方法决定了我们在开发和调试过程中如何查看和分析日志信息。本方案将介绍如何找到Java项目日志输出的路径,并提供代码示例。解决......
  • 怎么用InteIIiJ IDEA把java程序变成网站
    怎么用IntelliJIDEA把Java程序变成网站IntelliJIDEA是一款功能强大的集成开发环境(IDE),它支持Java和其他编程语言的开发。如果你想把Java程序变成一个网站,可以使用IntelliJIDEA来完成这个任务。下面我将指导你如何使用IntelliJIDEA将Java程序转换为网站。步骤1:创建一个JavaWeb......
  • 在线java 实体转 json
    在线Java实体转JSON的步骤和代码示例1.简介在Java开发中,我们经常需要将Java对象转换为JSON格式,以便在网络传输或者存储过程中使用。在本文中,我将向你介绍如何在线进行Java实体转JSON的处理,并提供相应的代码示例。2.实体转JSON的步骤下面是实现在线Java实体转JSON的整个流程,通......
  • Java提取Sql数据库数据,上传到接口测试
    一、pom.xml4.0.0HtyyDemoHtyyDemo0.0.1-SNAPSHOTorg.mybatismybatis3.4.6com.microsoft.sqlserversqljdbc42.0org.jsonjson20180130com.alibabafastjson2.0.15org.apache.httpcomponentshttpclient4.5.13org.slf4jslf4j-api1.7.25compile......
  • JavaScript复习知识点
    原型在JavaScript中,每个对象都有一个原型(prototype)。原型是一个对象,其他对象可以通过它来继承属性和方法。简单来说,对象通过其原型来共享和访问属性和方法。原型以原型链的形式连接在一起,形成了一个对象和原型之间的关系。当我们访问对象的属性或方法时,JavaScript引擎首先在......
  • android rxjava面试题
    RxJava面试题解析简介在Android开发中,使用RxJava能够简化异步操作、线程管理以及事件处理等方面的任务。在面试中,面试官常常会提问与RxJava相关的问题。本文将介绍如何使用RxJava来解决一个常见的面试题。面试题描述面试题要求使用RxJava实现一个简单的网络请求链式调用,实现如......