当前位置: 首页 > news >正文

`String`、`StringBuilder` 和 `StringBuffer`区别卓望一面面试题

文章目录

  • 1. String
        • 核心特性:不可变 (Immutable)
        • 应用场景(敲黑板!!考过!!)
        • 优势
        • 缺点
        • 解决了什么问题
  • 2. StringBuffer(synchronized同步锁)
        • 核心特性:可变 (Mutable) + 线程安全 (Thread-Safe)
        • 应用场景
        • 优势
        • 缺点
        • 解决了什么问题
  • 3. StringBuilder
        • 核心特性:可变 (Mutable) + 非线程安全 (Not Thread-Safe)
        • 应用场景(为什么用String,而不是StringBuilder?为什么用StringBuilder而不是String?)
        • 优势
        • 缺点
        • 解决了什么问题
  • 卓望一面面试题
  • 总结与选择指南

StringStringBuilderStringBuffer 是 Java 中处理字符串的三个核心类。它们的设计和存在是为了在不同场景下平衡性能线程安全易用性

下面我们来详细剖析每一个类,并回答它们分别适用于什么场景、有何优缺点,以及解决了其他类什么问题。


1. String

核心特性:不可变 (Immutable)

一旦一个 String 对象被创建,它包含的字符序列就永远不能被改变。任何对 String 对象的修改(如拼接、替换)都会导致创建一个全新的 String 对象。

应用场景(敲黑板!!考过!!)
  1. 存储固定不变的文本数据:如配置信息、URL、错误消息、数据库连接字符串等。
  2. 作为常量使用:在代码中定义的字符串字面量默认就是 String 对象。
  3. 需要安全性的场景:因为不可变,所以它被广泛用于网络连接、数据库用户名/密码等,防止在程序执行过程中被意外篡改。
  4. 作为 HashMap 的键HashMap 的键要求是不可变的。如果键的内容在放入 Map 后发生变化,将导致你再也找不到这个键对应的值。String 的不可变性完美符合这个要求。
优势
  • 线程安全:由于不可变,String 对象可以在多个线程之间自由共享,无需任何同步处理。一个线程无法改变另一个线程看到的 String 对象。
  • 可预测和安全:当你把一个 String 传递给一个方法时,你不用担心这个方法会改变字符串的内容。这使得代码更加健壮和安全。
  • 支持字符串常量池:JVM 通过字符串常量池来缓存字符串字面量,可以复用相同的字符串对象,节省内存。例如,String s1 = "hello"; String s2 = "hello"; s1s2 指向的是同一个对象。
缺点
  • 性能开销大(在频繁修改时):最大的缺点就是每次修改都会创建新对象。如果在循环中进行大量字符串拼接,会产生大量临时的、无用的对象,占用内存并触发频繁的垃圾回收(GC),严重影响性能

    // 性能极差的例子
    String result = "";
    for (int i = 0; i < 10000; i++) {result += "hello"; // 每次循环都会创建一个新 String 对象
    }
    
解决了什么问题

String 的设计初衷不是为了高效修改,而是为了提供一种可靠、安全的方式来表示和传递字符串数据。它的不可变性解决了在并发和复杂方法调用中数据被意外篡改的根本性安全问题。


2. StringBuffer(synchronized同步锁)

核心特性:可变 (Mutable) + 线程安全 (Thread-Safe)

StringBuffer 像一个可变的字符缓冲区。对它的修改(如 append, insert, delete)是直接在原对象上进行的,不会创建新对象。它的所有公开方法(如 append)都使用了 synchronized 关键字进行同步,保证了在多线程环境下的操作是安全的。

应用场景
  1. 多线程环境下的字符串拼接/修改:当多个线程需要共享并操作同一个字符串缓冲区时,StringBuffer 是唯一的正确选择。例如,多个任务同时向一个共享的日志记录器中追加日志内容。
  2. 需要兼容旧代码的场景StringBuffer 从 JDK 1.0 就存在了,是一些早期API的默认选择(尽管现在很多已被 StringBuilder 替代)。
优势
  • 线程安全:这是它相对于 StringBuilder 最核心的优势。可以在多线程环境中安全使用,无需开发者手动加锁。
  • 高性能(相对于String):在需要频繁修改字符串的场景下,由于其可变性,性能远高于 String
缺点
  • 性能开销(相对于StringBuilder):因为所有方法都加了 synchronized 同步锁,即使在单线程环境下,这个同步操作也会带来不小的性能开销。
解决了什么问题
  1. 解决了 String 在频繁修改时性能低下的问题:通过提供一个可变的字符缓冲区,避免了创建大量临时对象。
  2. 提供了多线程环境下安全修改字符串的方案:这是 StringBuilder 无法做到的。

3. StringBuilder

核心特性:可变 (Mutable) + 非线程安全 (Not Thread-Safe)

StringBuilder 在功能上与 StringBuffer 几乎完全一样,也是一个可变的字符缓冲区。唯一的、也是最关键的区别在于:它的方法没有 synchronized 修饰,因此不是线程安全的

应用场景(为什么用String,而不是StringBuilder?为什么用StringBuilder而不是String?)
  1. 单线程环境下的字符串拼接/修改:这是 StringBuilder 最主要、最广泛的应用场景。例如,在方法内部拼接SQL语句、构建JSON或XML字符串、循环拼接长字符串等。
  2. 对性能要求极高的场景:只要你能确保代码只在单个线程中运行,就应该优先使用 StringBuilder,因为它避免了 StringBuffer 的同步开销。
优势
  • 极致的性能:在单线程环境下,它是三者中执行效率最高的。因为它既是可变的,又没有同步开销。
缺点
  • 线程不安全:绝对不能在多个线程间共享同一个 StringBuilder 对象,否则会导致数据错乱、程序崩溃等不可预知的问题。
解决了什么问题
  1. 解决了 String 在频繁修改时性能低下的问题:和 StringBuffer 一样,通过可变性来优化性能。
  2. 解决了 StringBuffer 在单线程中性能过度损耗的问题:它去掉了 StringBuffer 的同步锁,将性能发挥到极致,成为单线程场景下的最佳选择。StringBuilder 是在 JDK 1.5 中被引入的,其目的就是为了替代单线程场景下的 StringBuffer

卓望一面面试题

在这里插入图片描述

String s="a"+"b"+"c";// A
String s="abc";//B
StringBuilder s=new StringBuilder("abc"//C

A和B经过编译器优化之后,一样。共同点是都会编译为普通字符串常量放入字符串常量池,
底层都是通过调用了StringBuilder的append方法来完成字符串拼接(环境是jdk-7,不要用jdk8及其以上环境,会有其他优化的!!)
在这里插入图片描述
在这里插入图片描述

总结与选择指南

特性StringStringBufferStringBuilder
可变性不可变 (Immutable)可变 (Mutable)可变 (Mutable)
线程安全安全 (Thread-Safe)安全 (Thread-Safe)不安全 (Not Thread-Safe)
性能低(频繁修改时)中等
核心机制创建新对象synchronized 方法无同步开销
引入版本JDK 1.0JDK 1.0JDK 1.5

如何选择?

  1. 字符串很少改变?

    • String。例如:String greeting = "Hello, World!";
  2. 单线程环境下,字符串需要频繁修改/拼接?

    • StringBuilder (首选)。例如:构建复杂的SQL查询语句。
    StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE ");
    if (name != null) {sql.append("name = '").append(name).append("'");
    }
    
  3. 多线程环境下,字符串需要被多个线程共享并修改?

    • StringBuffer。例如:一个全局计数器或日志缓冲区。
    // 假设这个 buffer 是一个被多个线程共享的静态字段
    private static StringBuffer sharedLogBuffer = new StringBuffer();// 某个线程在执行
    public void log(String message) {sharedLogBuffer.append(message).append("\n");
    }
    

一个简单的记忆法则:

  • String:不变。
  • StringBuilder:可变,单线程,速度快。
  • StringBuffer:可变,多线程,安全但稍慢。
http://www.dtcms.com/a/483091.html

相关文章:

  • 【11408学习记录】考研英语阅读长难句得分密码:5层拆解2016真题复杂句!
  • 网站建设启示金华网站建设团队
  • 做彩票网站代理犯法吗网站建设实施计划包括
  • 第三十五篇|日本语言学校的可计算结构:神户日语学院数据建模案例
  • 数据安全工具手册——便捷实用的安全工具集-20251014
  • 网站建设网络合同网站打开出现建设中
  • 办公用品网站模板建英文网站
  • 【编号28】中国九大流域范围-shp
  • FITC-SH的化学特性及其在分子标记与表面偶联中的实验应用
  • BITFIELD命令详解
  • 无锡模板网站设计公司无锡网站建设seo
  • ⸢ 柒-Ⅳ⸥⤳ 可信纵深防御建设方案:信任链构建可信策略
  • 德阳中恒网站建设杭州网站建设品牌
  • 如何做网站系统阿里云购买网站空间
  • 广州网站建设公司哪家服务好qq网页版登录官网登录入口
  • Docker(二) 容器技术发展史
  • MacOS本地数据库搭建
  • C语言--指针
  • 怎么打开域名网站长春网站排名
  • 做美容美发的网站有哪些天津市招标投标公共服务平台
  • SpringBoot基于工厂模式的多类型缓存设计
  • Redis中渐进式命令scan详解与使用
  • 江苏省建设厅网站 投诉wordpress页面写文章
  • Redis-主从复制和哨兵模式
  • 推荐一下做年会视频的网站做网站的上市公司
  • 淘宝网站建设论文河北城乡建设学校官方网站
  • 结构一次函数的图像
  • 1032 挖掘机技术哪家强
  • 程序员培训出来到底有没有用徐州seo计费管理
  • git status时发现有未提交的事件提交发现Git 锁文件冲突的问题解决办法