stringbuffer 长度_String、StringBuffer、StringBuiler它们有啥区别

点击上方“Java大讲堂”蓝字关注我们

469ee8d9d8677a785fe7b9b3d2f63c3f.gif

1.概述

StringStringbufferStringbuiler 一直是 java 面试中较为热点的问题,一般作为一个开场问题。

那么这三者之间有什么区别,如何根据场景来选择使用,本文将基于三者的源码、性能、以及面试常问点来进行分析。

String、StringBuffer、StringBuiler 底层源码

String 类

首先看一下 String 类的类图,它实现了 CharSequence 接口,也就是说 String 是 CharSequence 类型.

它的底层是被 final 修饰的字符数组,意味着一旦 String 被定义之后就不能够改变。

在日常我们做字符串拼接时,其实是一个创建新对象和回收旧对象的过程。以下面代码为例:

String str = "a";
str += "b";

当定义字符串 str 时并将值“a”赋给它,当执行第二段代码时,即实现 str 拼接“b”时,此时 JAVA 虚拟机创建了一个新对象 str,将拼接成的字符串“ab”赋给新 str。

GC 同时会回收旧的 str 对象,所以 str 并没有被更改,而是直接生成的新对象。若大量字符串拼接,利用 String 类型将严重影响性能。

f0dff16377acd573e821f3de958a6cf2.png
在这里插入图片描述
2abb8114a771efdb4d0f5cf85464782b.png
在这里插入图片描述

StringBuffer 类

StringBuffer 类继承自类 AbstractStringBuilder,AbstractStringBuilder 类封装了大量基础方法,包括数组扩容机制、拼接方法等。

StringBuffer 初始化时默认长度大小为 16,它的扩容方式是在旧的数据上乘以 2 并加 2 进行扩容。

StringBuffer 是线程安全的,可以查看其 append 方法(如下所示),由 synchronized 修饰,因此是线程安全的。


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

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}
f75f215e78b6d677dfda263c051b97f0.png
在这里插入图片描述
dbf75b91ee15830efd269cab5cf1ece8.png
在这里插入图片描述

StringBuiler 类

StringBuilder 与 StringBuffer 类似,均继承于 AbstractStringBuilder,所以其初始空间和扩容机制均相同。区别在于它的 append 方法不是由 synchronized 修饰,因此不是线程安全的。

@Override
public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}
c6e8c802c72d8214de518cea5db07801.png
在这里插入图片描述
40de930b98e486c93b7f42fa6d819a36.png
在这里插入图片描述

String、StringBuffer、StringBuilder 性能对比

测试代码如下

public class Test {

    private static final Integer time = 100000;

    public static void main(String[] args) {
        testString();
        testStringBuffer();
        testStringBuilder();
    }

    public static void testString() {
        String str = "";
        long start = System.currentTimeMillis();
        for (int i = 0;i             str += "a";
        }
        long end = System.currentTimeMillis();
        System.out.println("string:"+(end - start));
    }

    public static void testStringBuffer() {
        StringBuffer stringBuffer = new StringBuffer();
        long start = System.currentTimeMillis();
        for (int i = 0;i             stringBuffer.append("a");
        }
        long end = System.currentTimeMillis();
        System.out.println("stringBuffer:"+(end - start));
    }

    public static void testStringBuilder() {
        StringBuilder stringBuilder = new StringBuilder();
        long start = System.currentTimeMillis();
        for (int i = 0;i             stringBuilder.append("a");
        }
        long end = System.currentTimeMillis();
        System.out.println("stringBuilder:"+(end - start));
    }
}

3.2 测试结果如下:

315a2874b1de6575e963fc0812c264d9.png
在这里插入图片描述

结论:在单线程运行过程中,同样执行 10 万次拼接字符串"a",string 类型所耗费的时间远远大于 StringBuffer 和 StringBuilder。

面试常见问题举例

1.判断下面程序输出结果

String str1 = "helloworld";
String str2 = "hello" + "world";
System.out.println(str1 == str2); //true

2.判断下面程序输出结果

String str1 = "helloworld";
String str2 = "hello";
String str3 = str2+"world";
System.out.println(str1 == str3); //false

3.判断下面程序输出结果

String str1 = "helloworld";
final String str2 = "hello";
String str3 = str2+"world";
System.out.println(str1 == str3); //true

4.判断下面程序输出结果

public static void main(String[] args) {
    String str1 = "helloworld";
    final String str2 = returnStr();
    String str3 = str2 + "world";
    System.out.println(str1 == str3); //false
}

public static String returnStr() {
    return "hello";
}

5.判断下面程序输出结果

String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1 == str2); //false

6.判断下面程序输出结果

String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1 == str2.intern()); //true

5.小结

1.String 适用于字符串拼接较少、字符串变化较小的场合。

2.StringBuffer 适用于字符串连接操作比较频繁,且要求线程安全(多线程环境下操作)。

3.StringBuiler 适用于字符串连接操作比较频繁,且是单线程的情况。

---------------END----------------

欢迎关注"Java大讲堂"关注我们您将免费获取一份Java视频学习资料

资料详情请戳 →  Java学习资料

a853ce6876263644fc03b7a818bbc520.png

f4ac4b23b8335184b9ccbfee131f53aa.png

点赞+在看  对我们很重要哦 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这三个类都是用来处理字符串的类,但是它们之间有一些区别和联系。 1. StringString 类是 Java 中最基本的字符串类,它是不可变的,也就是说一旦创建了一个 String 对象,就不能再修改它的值。如果需要对一个 String 对象进行修改,那么就需要创建一个新的 String 对象。这种不可变性使得 String 对象在多线程环境下是安全的。 2. StringBuilder 类 StringBuilder 类是 Java 中可变的字符串类,它允许对字符串进行修改,而不需要创建一个新的对象。因此,StringBuilder 在处理大量字符串拼接的时候是非常高效的。不过,StringBuilder 并不是线程安全的,如果在多线程环境下使用 StringBuilder,就需要进行同步处理。 3. StringBufferStringBuffer 类和 StringBuilder 类很类似,都是可变的字符串类,也允许对字符串进行修改。不同的是,StringBuffer 是线程安全的,因此在多线程环境下使用 StringBuffer 是安全的。不过,由于需要进行同步处理,StringBuffer 的性能比 StringBuilder 差一些。 总的来说,如果需要在单线程环境下对字符串进行操作,那么可以使用 StringBuilder 类,因为它的性能比 StringBuffer 更好。如果需要在多线程环境下对字符串进行操作,那么应该使用 StringBuffer 类,因为它是线程安全的。而如果对字符串进行操作之后不需要再进行修改,那么可以使用 String 类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值