【Java 面试合集】String, StringBuffer和StringBuilder 之间的不同

String, StringBuffer和StringBuilder 之间的不同

1. 概述

嗨,大家好【Java 面试合集】又来了,今天我们分享的主题是String, StringBuffer和StringBuilder 之间的不同。 大家别看这个知识点不难,但是里面的细知识很多哦,好了废话不多说了,我们开始吧

2. 区别:

2.1 可变性

String 类型描述

String aa = "10";
        aa = "100";

上述代码是不是很眼熟啊,其实就是我们常写的代码,但是你以为它就是一个字符串吗??? 不不不

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

其实String底层实现是一个char类型数组,而且被final修饰过了。所以说String是不可变的。

如果是重复赋值的话,从第二次开始后开辟一个新的空间,然后将指针指向修改掉。

在这里插入图片描述

StringBuffer/ StringBuilder 类型描述

StringBuffer 继承于 AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;
}

StringBuilder 继承于 AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;
}

通过上述示例可以看到,其实本质上都是char类型数组,只不过没有被final修饰,是可变的。

2.2 StringBuilder 以及StringBuffer 不同

在这里插入图片描述
因为StringBuffer被synchronized 所修饰,所以是线程安全的。但是StringBuilder没有被synchronized修饰。

2.3 性能提升

每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用

public class Test001 {
    public static void main(String[] args) {
        String str = "";
        StringBuilder str1 = new StringBuilder();

        long lStart1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            str += "a";
        }
        long lEnd1 = System.currentTimeMillis();

        long lStart2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            str1.append("a");
        }
        long lEnd2 = System.currentTimeMillis();

        System.out.println("String花费时长:" + (lEnd1 - lStart1)); // 4229
        System.out.println("String花费时长:" + (lEnd2 - lStart2)); // 1
    }
}

2.4 扩容机制

  1. 默认的StringBuilder长度, 如果是以无参的方式进行调用的话,默认的长度就是16
    public StringBuilder() {
        super(16);
    }
  1. 扩容的条件,满足什么条件的时候会选择扩容呢
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}
  1. 扩容的大小. 扩容的公式是:旧长度 << 1 + 2. ,例如:旧长度是10的话,新的长度就是22
    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;
    }
  1. 为什么要执行+2呢

因为我们可以在执行new StringBuilder 的时候,传递一个初始化的长度。如果没有+2的操作,传递的初始化长度又是0. 那么初始化的长度就是0.

目的为了防止初始容量是0.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值