Java经典面试题——String、StringBuffer、StringBuilder有什么区别?

news2024/9/25 9:17:01

典型回答

String 是Java 语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类,被声明成为 final class ,所有属性也都是 final 的。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的 String 对象。由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明显影响。

StringBuffer 是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,我们可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是StringBuilder。

StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 没有本质区别,但是它去掉了线程安全的部分,有效减小了开销,是绝大部分情况下进行字符串拼接的首选。

知识扩展

关于String类

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 的,意味着它不能被子类继承
  • String 类实现了 Serializable 接口,意味着它可以序列化
  • String 类实现了 Comparable 接口,意味着最好不要用 ‘==’ 来比较两个字符串是否相等,而应该用 compareTo() 方法去比较
  • StringBuffer、StringBuilder 和 String 一样,都实现了 CharSequence 接口,所以它们仨属于近亲。由于 String 是不可变的,所以遇到字符串拼接的时候可以考虑一下String 的另外两个好兄弟,StringBuffer 和 StringBuilder ,它们俩个是可变的。
  • 每一个字符串都会有一个 hash 值,这个哈希值在很大概率是不会重复的,因此 String 很适合来作为 HashMap 的键值。

为什么String 是不可变的?

  • String 类被 final 关键字修饰,所以它不会有子类,这就意味着没有子类可以重写它的方法,改变它的行为。
  • String 类的数据存储在 byte[ ] 数组中,而这个数组也被 final 关键字修饰了,这就表示 String 对象是没法被修改的,只要初始化一次,值就确定了。

为什么要这样设计呢?

  • 第一,可以保证 String 对象的安全性,避免被篡改,毕竟像密码这种隐私信息一般就是用字符串存储的。
  • 第二,保证哈希值不会被频繁变更。毕竟要经常作为哈希表的键值,经常变更的话,哈希表的性能就会很差劲。
  • 第三,可以实现字符常量池。

由于字符串的不可变性,String对象一旦被创建后就固定不变了,对 String 对象的任何修改都不会影响到原来的字符串对象,都会生成新的字符串对象。

关于StringBuffer

由于字符串是不可变的,所以当遇到字符串拼接(尤其是使用+号操作符)的时候,就需要考量性能的问题,你不能毫无顾虑地生产太多 String 对象,对珍贵的内存造成不必要的压力。

于是 Java 就设计了一个专门用来解决此问题的 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);
    }

    // 其他方法
}

不过,由于 StringBuffer 操作字符串的方法加了 synchronized 关键字进行了同步,主要是考虑到多线程环境下的安全问题,所以执行效率会比较低。

关于StringBuilder

与 StringBuffer 相比除了类名不同,方法没有加 synchronized,基本上完全一样。

实际开发中,StringBuilder 的使用频率也是远高于 StringBuffer。

Java 编译器将字符串拼接操作(+)转换为了 StringBuilder 对象的 append 方法,然后再调用 StringBuilder 对象的 toString 方法返回拼接后的字符串。

来看一下 StringBuilder 的 toString 方法:

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

value 是一个 char 类型的数组:

/**
 * The value is used for character storage.
 */
char[] value;

在 StringBuilder 对象创建时,会为 value 分配一定的内存空间(初始容量 16),用于存储字符串。

/**
 * Constructs a string builder with no characters in it and an
 * initial capacity of 16 characters.
 */
public StringBuilder() {
    super(16);
}

随着字符串的拼接,value 数组的长度会不断增加,因此在 StringBuilder 对象的实现中,value 数组的长度是可以动态扩展的,就像ArrayList那样。

继续来看 StringBuilder 的 toString 方法:

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

value 用于存储 StringBuilder 对象中包含的字符序列。count 是一个 int 类型的变量,表示字符序列的长度。toString() 方法会调用 new String(value, 0, count),使用 value 数组中从 0 开始的前 count 个元素创建一个新的字符串对象,并将其返回。

再来看一下 append 方法:

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

实际上是调用了 AbstractStringBuilder 中的 append(String str) 方法。在 AbstractStringBuilder 中,append(String str) 方法会检查当前字符序列中的字符是否够用,如果不够用则会进行扩容,并将指定字符串追加到字符序列的末尾。

在 jdk 中 StringBuilder 类的实现中,采用 建造者模式 的思想。具体分析如下:

StringBuilder 类继承自 AbstractStringBuilder,而 AbstractStringBuilder实现了 Appendable接口。
AbstractStringBuilder 虽然是一个抽象类,但是它实现了 Appendable 接口中的各个 append() 方法,
因此在这里 Appendable 接口是一个抽象建造者,而 AbstractStringBuilder 是建造者,只是不能实例化。
对于 StringBuilder 类,它既充当了指挥者角色,同时充当了具体的建造者,建造方法的具体实现是由 AbstractStringBuilder 完成,
StringBuilder 继承了 AbstractStringBuilder。

在这里插入图片描述

建造者模式的4个角色

  • Product(产品角色):一个具体的产品对象;
  • Builder(抽象建造者):创建一个Product对象的各个部件指定的接口/抽象类;
  • ConcreteBuilder(具体建造者):实现接口,构建和装配各个部件;
  • Director(指挥者):构建一个使用Builder接口的对象。有两个作用:①隔离了客户与对象的生产过程;②负责控制产品对象的生产过程。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习100天(三十五):035 贝叶斯公式

《机器学习100天》完整目录:目录 机器学习100天,今天讲的是:贝叶斯公式! 好了,上一节介绍完先验概率、后验概率、联合概率、全概率后,我们来看这样一个问题:如果我现在挑到了一个瓜蒂脱落的瓜,则该瓜是好瓜的概率多大? 显然,这是一个计算后验概率的问题,根据我们之…

基于DSP的三相开关霍尔永磁同步电机控制

0 前言 本文本应该是一篇 记录我使用DSP28377D控制一个基于三相开关霍尔传感器的高速永磁同步电机全过程的长文&#xff0c;但大部分零散的知识点我都已经写成单独的博客了&#xff0c;所以本文更像是一个知识框架的梳理。本文最终目的是实现高速PMSM的电流-速度双闭环&#x…

[LK光流法,disflow using Dense Inverse Search, VariationalRefinement变分优化 原理和代码]

文章目录1.Fast Optical Flow using Dense Inverse Search1.1 W的含义&#xff1a;1.2 LK光流模型1.3 LK光流模型求解&#xff08;不含迭代&#xff09;1.4 LK光流模型迭代求解1.5 dis_flow方法中的 LK光流模型1.6 disflow代码分析2.0 disflow中的VariationalRefinement方法2.0…

大佬们都说tcp有黏包的问题,tcp却说:我冤枉!

相关参考添加链接描述 相关参考 什么是tcp TCP,全称Transmission Control Protocol&#xff0c;是一种传输控制协议&#xff0c;TCP协议也是计算机网络中非常复杂的一个协议 tcp的特点 tcp是面向连接的协议tcp是端到端的链接tcp提供可靠的传输服务tcp协议提供双工通信tcp是…

【计算机考研408】快速排序的趟数问题 + PAT 甲级 7-2 The Second Run of Quicksort

前言 该题还未加入PAT甲级题库中&#xff0c;可以通过购买2022年秋季甲级考试进行答题&#xff0c;纯考研题改编 快速排序 常考的知识点 快速排序是基于分治法快速排序是所有内部排序算法中平均性能最优的排序算法快速排序是一种不稳定的排序算法快速排序算法中&#xff0c…

异步Buck和同步Buck的特点

1 介绍 随着时代的发展&#xff0c;工业&#xff0c;车载&#xff0c;通信&#xff0c;消费类等产品都提出了小型化&#xff0c;智能化的需求。相应的&#xff0c;对于这些系统中的电源模块提出了小型化的要求。目前&#xff0c;市场上依然存在很多异步Buck电源管理芯片使用的场…

atomic 原子操作

atomic 原子操作前言atomic_t定义内核中的实现armv7的实现armv8的实现Exclusive monitor实现所处的位置External exclusive monitorAtomic指令的支持QA前言 修改一个变量会经过读、修改、写的操作序列。但有时该操作序列在执行完毕前会被其他任务或事件打断。 比如在多CPU体系…

python基础学习3--切片(slice)

在python中&#xff0c;切片&#xff08;slice&#xff09;是对序列型对象&#xff08;如list,string,tuple)的一种高级索引方法。普通索引只取出序列一个下标对应的元素&#xff0c;而切片取出序列中一个范围对应的元素&#xff0c;这里的范围不是狭义上的连续片段。通俗一点就…

CLion Debug 调试 Makefile 构建的 C 语言程序断点不起作用

最近在研究 jattach&#xff0c;打算在本地调试项目&#xff0c;发现 CLion 可以正常编译运行代码&#xff0c;却无法断点 Debug。由于笔者对 C/C 项目不熟悉&#xff0c;在此记录研究过程中遇到的一些基本问题与解决方法。 文章目录解决方式尝试过的手段【未解决】找 Native D…

RIG Exploit Kit 仍然通过 IE 感染企业用户

RIG Exploit Kit 正处于最成功的时期&#xff0c;每天尝试大约 2000 次入侵并在大约 30% 的案例中成功&#xff0c;这是该服务长期运行历史中的最高比率。 通过利用相对较旧的 Internet Explorer 漏洞&#xff0c;RIG EK 已被发现分发各种恶意软件系列&#xff0c;包括 Dridex…

内科大机器学习期末重点

1. 什么是机器学习 &#xff08;由于图床原因导致部分图片错位&#xff0c;可以借鉴着看&#xff09; 语音识别算法推荐人脸识别垃圾邮件过滤贷款资格审核 2. 学习的概念 与经验有关 学习可以改善系统性能 学习是一个有反馈的信息处理与控制过程 3. 学习分类&#xff1a…

996的压力下,程序员还有时间做副业吗?

996怎么搞副业&#xff1f; 这个问题其实蛮奇怪的&#xff1a;996的压力下&#xff0c;怎么会还想着搞副业呢&#xff1f; 996还想搞副业的原因有哪些&#xff1f; 大家对于996应该都不陌生&#xff0c;总结就是一个字&#xff1a;忙。 996的工作性质就是加班&#xff0c;就…

基于龙芯+国产FPGA 的VPX以太网交换板设计(二)

3.1 板卡技术要求 3.1.1 主要性能指标 本着向下兼容的原则&#xff0c;以太网交换板的设计尽量保留传统信息处理平台的基本功 能和接口&#xff0c;重点考虑提升设备的性能和扩展性。本课题以太网交换板的主要性能指标 如下&#xff1a; &#xff08;1&#xff09; 具有大容量无…

一文搞懂华为防火墙的原理和配置

“防火墙”一词起源于建筑领域&#xff0c;用来隔离火灾&#xff0c;阻止火势从一个区域蔓延到另一个区域。引入到通信领域&#xff0c;防火墙这一具体设备通常用于两个网络之间有针对性的、逻辑意义上的隔离。这种隔离是选择性的&#xff0c;隔离“火”的蔓延&#xff0c;而又…

mac安装docker hub及使用

1. docker hub安装 官网&#xff1a;Docker https://hub.docker.com/ 去官网 下载 Docker.dmg 并安装 2. docker hub的使用 step1: 首先克隆一个仓库 Getting Started 项目是一个简单的Github仓库&#xff0c;他包含了你创建镜像的所有东西&#xff0c;并且可以把他当容…

文心一言的蝴蝶振翅,云计算的飓风狂飙

ChatGPT带来的多米诺效应正在不断涌现。社会各界都在关注一系列问题&#xff0c;比如中国版ChatGPT什么时候能来到&#xff1f;其效果如何&#xff1f;类ChatGPT应用的投资与创业前景会怎样&#xff1f;相关产品能带来哪些应用价值&#xff1f;随着百度文心一言等产品相继官宣&…

面试问题【数据库】

数据库数据库的三范式是什么drop、delete、truncate 分别在什么场景之下使用char 和 varchar 的区别是什么数据库的乐观锁和悲观锁是什么SQL 约束有哪几种mysql 的内连接、左连接、右连接有什么区别MyIASM和Innodb两种引擎所使用的索引的数据结构是什么mysql 有关权限的表都有哪…

SpringSecurity常见面试题汇总(超详细回答)

1.什么是Spring Security&#xff1f;核心功能&#xff1f;Spring Security是一个基于Spring框架的安全框架&#xff0c;提供了完整的安全解决方案&#xff0c;包括认证、授权、攻击防护等功能。其核心功能包括&#xff1a;认证&#xff1a;提供了多种认证方式&#xff0c;如表…

线性表 链表表示

初识链表 用一组物理位置任意的存储单元来存放线性表的数据元素。这组存储单元既可以是连续的&#xff0c;也可以是不连续的&#xff0c;甚至是零散分布在内存中的任意位置上的。链表中元素的逻辑次序和物理次序不一定相同。 在存储自己内容的同时也存储下一个元素的地址。存…

Adobe illustrator使用教程

抓手工具&#xff1a;绘制大型图片拖动图片 画放大缩小&#xff1a;Alt鼠标滚轮 间接选择工具&#xff1a;点击图标shift 进行多个对象选择&#xff0c;再次点击取消选择&#xff08;用于对多个对象进行批量操作&#xff09; 直接选择工具&#xff1a;可以对图案本身进行精细选…