JAVA面试:String、StringBuffer和StringBuilder区别

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: `String`是不可变的,`StringBuffer`和`StringBuilder`是可变的。`String`的不可变性源于其内部的`final char[]`数组,这意味着每次修改都会创建新对象。`StringBuffer`线程安全,方法同步,适合多线程环境,但效率较低;`StringBuilder`非线程安全,无同步,单线程中效率更高。两者初始容量相同,扩容机制也一样。

 


1. String、StringBuffer和StringBuilder区别

答:String是不可变的,而StringBuffer和StringBuilder是可变的。

这样回答肯定是不满意的,面试官希望听到的是你能说出个为什么?而不是给我一个结论,只说结论面试官会认为你只是背了面试题而已。

2. 为什么String是不可变的?

简单的讲String是内部结构如下

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

image.gif

是用final char value[]来存储字符串, 所以上不可变的。这么说肯定凉了。

final说明: 修饰的类不能被继承、修饰的方法不能被重写、修饰的基本数据类型变量是其值不能改变、修饰的引用类型变量是不能再指向其他对象。

所以final修饰的char value[],其组据是可变的。

为什么是不可变呢? 先看String的Api,提供了哪些public方法

image.png image.gif image.png

从源码中可以看出

  • String 并没有提供一个可以修改数组值的方法
  • String是final类,不能被继承,也不可能有子类来修改

3.为什么StringBuffer和StringBuilder是可变的?

StringBugger和StringBuilder都继承自AbstractStringBuilder,
StringBugger和StringBuilder存放字符串都放在AbstractStringBuilder的char[] value中。
而AbstractStringBuilder提供如append来修改value的值。所以是可变的。

image.gif

4. StringBuffer和StringBuilder的区别?

1. 先看看源码,如下

image.png

StringBuffer的公开方法加了对象锁,所以是线程安全的,而StringBuilder没有,所以是线程不安全

2. StringBuffer的API加了对象锁,执行速度慢(效率慢)。StringBuilder未加锁,执行速度快(效率高)。

3. toString方法不同,直接看源码

image.png

注: toStringCache的定义是 private transient char[] toStringCache

从源码看出:

  • StringBuffer的toString都会直接使用缓存区的toStringCache值来构造一个字符串
  • 而StringBuilder是需要复制一次字符数组,再构造一个字符串

5. StringBuffer和StringBuilder相同之处?

  1. 字符串都可变
  2. 默认初始容量都是16
  3. 扩容机制相同。源码如下:
都是调父类AbstractStringBuilder 的扩容方法,源码如下:
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
    private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

image.gif


目录
相关文章
|
2天前
|
移动开发 前端开发 JavaScript
Java和web前端,IT新人该如何选择?,2024年最新Web前端内存优化面试
Java和web前端,IT新人该如何选择?,2024年最新Web前端内存优化面试
|
2天前
|
索引
【ES6新语法】let、const、var的区别,你学会了面试官没话说
【ES6新语法】let、const、var的区别,你学会了面试官没话说
|
2天前
|
Java 数据库连接 数据库
spring--为web(1),富士康java面试题整理
spring--为web(1),富士康java面试题整理
|
2天前
|
前端开发
vue2与vue3双向数据绑定的区别,前端面试自我介绍
vue2与vue3双向数据绑定的区别,前端面试自我介绍
|
2天前
|
存储 安全 Java
Java中的这些String特性可能需要了解下
Java中的String特性你知道哪些?虽然String很常见,通过源码可以看到String的值传递、字符串表和不可变性。本文基于JDK17说明。
9 1
|
2天前
|
安全 Java 数据库
Spring boot 入门教程-Oauth2,java面试基础题核心
Spring boot 入门教程-Oauth2,java面试基础题核心
|
2天前
|
Java
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
|
3天前
|
Java 索引
String字符串常用函数以及示例 JAVA基础
String字符串常用函数以及示例 JAVA基础
|
4天前
|
Java 编译器 ice
【Java开发指南 | 第十五篇】Java Character 类、String 类
【Java开发指南 | 第十五篇】Java Character 类、String 类
24 1
|
2天前
|
存储 Java
Java基础复习(DayThree):字符串基础与StringBuffer、StringBuilder源码研究
Java基础复习(DayThree):字符串基础与StringBuffer、StringBuilder源码研究
Java基础复习(DayThree):字符串基础与StringBuffer、StringBuilder源码研究
http://www.vxiaotou.com