Java中String,StringBuffer和StringBuilder的区别

手把手教你编写I2C读写EEPROM代码(驱动层实现) 从底层寄存器配置到时序控制,详解如何编写可移植的I2C读写EEPROM代码,覆盖起始信号、地址帧、数据收发及ACK应答等关键环节,确保在STM32、ESP32等主流平台稳定运行,真正落地i2c读写eeprom代码需求。 阅读详情

先说结论,

  • String对象是不可变的,对String对象的增删改,实际上是创建了一个新的对象。
  • StringBuffer是可变的,对StringBuffer对象的增删改是不会创建新对象的,并且它是线程安全的。
  • StringBuilder是可变的,对StringBuilder对象的增删改是不会创建新对象的,它不是线程安全的。

1.String

结论:String对象是不可变的,对String对象的增删改,实际上是创建了一个新的对象。

上论据,我们直接看一下String类的源码。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    ...
    // 省略其他代码
    ...

}

可以看到String类中有一个char类型的数组value,官方注释说明了这个数组用来存String字符串。

数组被final关键字修饰了,众所周知,Java语言中,被final修饰的都是不可变的。

拓展

再看看官方注释对String类的描述

/**
* The String class represents character strings. All string literals in Java 
* programs, such as "abc", are implemented as instances of this class.
*/

翻译成中文就是

String类表示字符串。Java程序中的所有字符串文本(如“abc”)都作为此类的实例实现。

所以我们如果直接使用"abc","123"等字符串,都是String类型的。

2.StringBuffer

结论:StringBuffer是可变的,对StringBuffer对象的增删改不会创建新对象,且它是线程安全的。

上论据,看源码

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
  // 省略代码
}

StringBuffer本身没有定义字符串的存储结构,但StringBuffer是继承自AbstractStringBuilder这个抽象类的,我们再看看AbstractStringBuilder的源码。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     * 
     * 翻译;用来存储字符
     */
    char[] value;


    /**
     * The count is the number of characters used.
     * 
     * 翻译;用来记录当前已经使用的字符的数量
     */
    int count;

    // 省略其他代码
}

AbstractStringBuilder类中和String类一样,用一个数组作为字符串的数据结构,但它没有被final修饰,是可以修改的。

至此,我们得到结论的第一部分,StringBuffer是可变的。

接着我们看一下StringBuffer【添加字符串】的方法,即append的方法是怎么实现的,看看操作StringBuffer的时候是否会产生新对象。

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

append方法核心是调用了父类的append方法,即AbstractStringBuilder类的append方法,那我们再去AbstractStringBuilder那里看看。 

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;
}

这里通过调用String类的getChars方法来添加字符串。

str.getChars(0, len, value, count);

这几个参数需要注意一下。

str就是append(String str)里被添加的字符串,是String类型的。

value就是AbstractStringBuilder中可变的数组。

count 是AbstractStringBuilder使用来记录当前value数组已经被使用的数量。

继续看String类中的getChars方法是怎么实现的。

    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

这里最核心的代码就是System.arraycopy,这个方法的作用是什么呢?

    /**
     * Copies an array from the specified source array, 
     * beginning at the specified position,
     * to the specified position of the destination array.
     * A subsequence of array components are copied from the source array
     * referenced by src to the destination array referenced by dest.
     * The number of components copied is equal to the length argument.
     * The components at positions srcPos through srcPos+length-1
     * in the source array are copied into positions destPos through
     * destPos+length-1, respectively, of the destination array.
     *
     * Params:
     * src – the source array.
     * srcPos – starting position in the source array.
     * dest – the destination array.
     * destPos – starting position in the destination data.
     * length – the number of array elements to be copied.
     */
    public static native void arraycopy(Object src,  int  srcPos, 
                                        Object dest, int destPos,
                                        int length);

这是一个本地方法,关于什么是本地方法,朋友们百度一下很快知道是什么,我就不赘述了,arraycopy的源码注释如上,翻译过来就是

把一个指定的源数组,从指定位置开始,复制到另一个目标数组的指定位置。
把一个源数组的子序列(也就是数组的的一部分)从src引用的源数组复制到dest引用的目标数组。

复制的序列长度数等于长度参数length。
将源数组中位置 srcPos 到 srcPos+length-1的数据序列
复制到目标数组destPos 到 destPos+length-1的位置。

参数:
    src – 源数组。
    srcPos – 源数组中的起始位置。
    dest – 目标数组。
    destPos – 目标数组中的起始位置。
    length – 要复制的数组元素数。

System.arraycopy的作用就是将一个数组某一部分复制到另外一个数组的某个指定位置。

知道这个方法是干什么的,我们再回去看看当我们使用StringBuffer添加一个字符串的时候,传给arraycopy的参数的值分别是什么。

src – 被添加的字符串数组,即append的入参。
srcPos – 源数组中的起始位置,这里是0。
dest – 目标数组,这里是StringBuffer里面的可变数组。
destPos – 目标数组的起始位置,这里使用了count,即当前已经使用的字符的数量,
          就是StringBuffer可变数组的最后一个字符的位置 + 1。
length – 要复制的数组元素数,被添加的字符串数组的长度。

从这里我们可以看出,每次StringBuffer调用append方法,都是将一个String类型的字符串追加到了StringBuffer的可变数组中,没有创建新的对象,StringBuffer其他操纵字符串的方法本质也是如此,就不一一列出来,有兴趣可以看源码。

结论第二阶段,StringBuffer是可变的,且操作StringBuffer不会产生新对象。

StringBuffer的每个方法都有一个synchronized关键字进行修饰,加了这个关键字,就说明这个方法加上了synchronized锁,加上了synchronized锁,就一定能避免线程安全问题。

所以得到最终结论,StringBuffer是可变的,操作StringBuffer不会产生新对象,且StringBuffer是线程安全的。

3.StringBuilder

结论:StringBuilder是可变的,对StringBuilder对象的增删改是不会创建新对象的,它不是线程安全的。

上论据:

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    // 省略代码
}

可以看到,StringBuilder和StringBuffer一样,也是继承自AbstractStringBuilder来实现字符串的增删改的,那么对于是否可变和是否会产生新对象的分析,所有的分析都和StringBuffer是一样的。

不过,StringBuilder的方法都没有使用synchronized锁。

直接看StringBuffer和StringBuilder的append方法

public final class StringBuffer
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
{
    @Override
    public synchronized java.lang.StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
}

public final class StringBuilder
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
{
    @Override
    public java.lang.StringBuilder append(String str) {
        super.append(str);
        return this;
    }
}

所以,StringBuilder是可变的,对StringBuilder对象的增删改是不会创建新对象的,但它不是线程安全的。

适用场景

分析

  • StringBuffer加了锁,所以创建StringBuffer对象的性能比StringBuilder差。
  • String对象不可变,如果对字符串的改变比较多,就会产生一堆String对象占用内存。

结论

  • 如果不需考虑线程安全,且对字符串的修改比较频繁,应该使用StringBuilder对象,使用StringBuffer对象因为加了锁影响创建效率,String对象会占用内存。
  • 如果不需考虑线程安全,且修改不频繁,可以直接使用String对象,这时候使用String对象,对内存影响不大,而且对开发者而言,操作比较方便。
  • 如果需要考虑线程安全,那就只能使用StringBuffer。
缠论 公式 自动画线 画笔 中枢 买卖点 源代码 【代码】缠论 公式 自动画线 画笔 中枢 买卖点 源代码。 阅读详情

相关推荐

从DIY到实战:手把手教你搭建一个媲美吉时利2450的nA级电流源表(附原理图与避坑指南)

本文详细解析如何从零打造nA级精密电流源,涵盖核心设计原理、PCB布局技巧、热电偶效应应对及校准验证体系。通过低成本替代方案和优化设计,实现媲美商用源表的性能,特别适合硬件爱好者和独立开发者。文章还提供原理图与避坑指南,助你轻松搭建高精度电流源系统。

weixin_42656416的博客 292

面试

一、java基础 1、什么是面向对象? JAVA是面向对象的编程语言,面向对象编程(OOP)是软件开发过程中使用的一种思维方式,通过面向对象思维方式进行编程。面向对象思想就是通过调用其他对象,帮助我们完成某些功能,在这个处理问题的过程中,我们始终处于调用者、指挥者的角色,提供功能我们不干,交给其他对象来干。 面向对象编程:采用面向对象思考方式,解决编程中遇到的问题,侧重将具体的功能封装到一个对象当中,在处理问题时,通过调用对象,由对象进行工作,程序员在处理问题的过程中处于调用者、指挥者的角色。 面向对象编程

weixin_44378081的博客 1433

基于h5端的视频录制和回溯功能的实现

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

发果叁 3191

有关string stringbuff stringbuild 的区别

string stringbuff stringbuild的执行效率: stringbuild>stringbuff>string String类是不可变类,任何对String的改变都会引发新的String对象的生成; StringBuffer是可变类,任何对它所指代的字符串的改变都不会产生新的对象,线程安全的。 StringBuilder是可变类,线性不安全的,不支...

dfug3303的博客 847

【mysql8.0.33安装详情教程】

8、进入Account and Roles界面,输入密码,再点击next(密码随便输,自己记住就行)11、进入Apply Configuration界面,直接点Execute,等待应用成功。14、输入密码,点击check,检查是否正确。3、下图是选择安装类型,选择默认安装就可以,然后点击“next”。5、进入Product Configuration,点击next。9、进入Windows Service界面,直接点击next。15、点击Execute执行安装(完成后点击Finish)二、验证是否安装成功。

98渣渣辉的博客 2113

【深度学习】手把手教你在远程服务器上跑 YOLOv3 相关代码(含环境配置)

这篇文章主要记录了如何配置项目环境以及如何在远程服务器上跑 YOLOv3 模型。

作者正在煮茶中... 2384

SpringBuffer,SpringBuilder,Spring之间的关系区别

SpringBuffer,SpringBuilder,Spring之间的关系区别: 0、String 是不可变的对象, 每次对 String 类型进行改变的时候都相当于生成了一个新的 String 对象,然后将指针指向新的 String 对象,每次生成对象都会对系统性能产生影响,所以经常改变内容的字符串最好不要用 String 1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的。 2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行

weixin_49071539的博客 7212

STM32掉电保存配置参数技巧

本文介绍了使用STM32内置备份寄存器(BKP)实现掉电保存配置参数的方法。相比外接EEPROM或Flash,备份寄存器无需外设但存储容量有限,需通过VBAT引脚连接纽扣电池供电。文章详细说明了初始化步骤,包括使能PWR时钟、允许访问备份寄存器等操作,并提供了RTC初始化的代码示例。同时介绍了HAL库中读写备份寄存器的函数使用方法,包括HAL_RTCEx_BKUPWrite和HAL_RTCEx_BKUPRead函数的具体参数和调用示例。该方法适用于需要小容量数据掉电保存的应用场景。

hanhanhan233的博客 947

StringBuffer和SpringBuilder 区别简述

StringBuffer和SpringBuilder 都是AbstractStringBuilder 的子类、 单纯从StringBuffer.append 和SpringBuilder.append 方法上来看最大的区别是StringBuffer.append 存在synchronized,其他的都一样,而synchronized 是重量级锁,平常的使用过程中应使用SpringBuilder 如下 1. StringBuilder实现 @Override public StringBu.

黑夜中的斗狼 2931

深度学习|卷积神经网络

介绍卷积神经网络基本理论,包括卷积层、池化层和全连接层,并阐述LeNet卷积神经网络的构建过程。

weixin_58243219的博客 5727

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

算法大师! 793

Spring

★4.IOC容器构建流程?★1.Spring和和的区别?①值可变性Spring中的值是final修饰的,不可变,当试图修改这个不可变值时等于创建一个新的对象。和则是可变的②Spring:值不可改(安全)自带锁(安全)值可改,无锁(不安全)③Spring:每次修改创建新对象(效率最慢)值可改但自带锁(效率高于Spring但低于SpringBuilder)值可改,无锁(效率最快)2.

LHR2575050945的博客 1348

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java基础:String、StringBuffer、StringBuilder的区别

这篇文章主要介绍了String、StringBuffer、StringBuilder的区别详细教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下。放假在家里休息,闲来无事,想巩固巩固自己的基础知识。Java基础这个我会一直更新的,希望大家关注 收藏 点赞。

weixin_42188778的博客 3万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java中String,StringBuilder和StringBuffer的区别

这三个类的主要区别在两个方面:运算速度(运算性能或执行效率)和线程安全性。 1、运算速度比较(通常情况下):StringBuilder &gt; StringBuffer &gt; String String是final类不能被继承且为字符串常量,而StringBuilder和StringBuffer均为字符串变量。String对象一旦创建便不可更改,而后两者是可更改的,它们只能通过构造函数来...

Calvin的博客 3万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【Java】中的String、StringBuffer和StringBuilder的区别

在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。需要注意的是,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。至于为啥是不可变,我们可以来看下面这个图,发现String是用final修饰的,导致了他的不可变。 接下来我们从内存的角度来看一下,操作String类型时候的内存变化不难看出:初始String值为"Hello",然后在这个字符串后面加上新的字符串"world",这个过程重新

秋名山码民的技术小屋 1万+

java中String、StringBuffer和StringBuilder的区别

简单介绍 java中用于处理字符串常用的有三个类: 1、java.lang.String 2、java.lang.StringBuffer 3、java.lang.StrungBuilder 三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用。 StringBuffer是线程安全,可以不需要额外的同步用于多线程中; StringBuilder是非同步,运行于多线程中就需要使用着单独同步...

fu6543210的博客 4321

Java String、StringBuffer 和 StringBuilder 的区别

String 类型和 StringBuffer 的主要性能区别:String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。

2403_87486006的博客 1320

Java中的String,StringBuilder,StringBuffer三者的区别

Java中的String,StringBuilder,StringBuffer三者的区别

这个人很懒,什么都没有留下。 4818

【Java面试必修课】String、StringBuilder和StringBuffer的区别详解

在Java开发中,字符串操作是常见的需求。String和是Java中用于处理字符串的三个核心类,它们各自具有不同的特性和使用场景。本文将深入探讨它们的区别,帮助你在实际开发中选择合适的类。(文末有灵魂总结表格以及近年来面试中最常见的问题以及答案,赶时间的同学可直接划到底部)

lisort的博客 2495

JAVA基础之String StringBuffer和StringBuilder三者的区别

今天来复习下java基础中,String StringBuffer和StringBuilder三者的区别,这也是面试的常考点之一,话不多说,直接上干货! String ​ String最常用的字符串,在java中String属于对象,同时由于String类是final修饰的,所以String的值是无法改变的。看到这里肯定有疑问 比如以下代码 String a = "abd"; System.out.println(a); a="c12"; System.out.println(a); 运行结果后,

weixin_42194019的博客 875

java中String、StringBuffer、StringBuilder区别

java字符串的应用场景十分广泛、我们常用String、StringBuffer、StringBuilder来进行字符串的存储,但是他们之间有什么区别呢 1.String 1).不可被继承,因为String是一个被final修饰的类,无法被子类继承 2).值不可变,每一个String对象都是一个新对象、从源码可以查看、String的值通过一个字符数组变量value[]进行值存储、该值是被final修饰,不可改变,所以每一个String对象都是一个新对象;在高并发环境中、若大量使用String对字符串进行操作

qq_38318330的博客 7888

Java中String、StringBuffer、StringBuilder的区别

目录Java中String、StringBuffer、StringBuilder的区别1. String2. StringBuffer3. StringBuilder Java中String、StringBuffer、StringBuilder的区别 1. String String 是不可变的字符序列,而 StringBuilder 和 StringBuffer 是可变的字符序列; 2. StringBuffer 拼接字符串时执行速度:StringBuilder > StringBuffer &gt

weixin_39325834的博客 193

Java中String, StringBuffer,StringBuilder的区别

java中String、StringBuffer、StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题。现在总结一下,看看他们的不同与相同。 1.可变与不可变 String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。 private final char value[]; String 为不可变对象,一旦被创建,就不能修改它的值。对于已经存在的String对象的修改都是重新创建一个新的.

shenju2011的博客 228

Java中String StringBuffer和StringBuilder的区别是什么

String StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的? 可变性 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。 在 Java 9 之后,String 类的实现改用 byte 数组存储字符串 private fin...

java阳旭的博客 1858
上一篇: java中“==”和equals的区别
下一篇: 设计模式 | 为什么要学设计模式?懂兵法才能当好将军
大树x
博客等级 码龄10年 5粉丝 9原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值