面向八股文编程(一)

一、String 、StringBuilder 、StringBuffer 的区别

1、答案
1、String 类型是不可变的(immutable),一旦创建就不能更改它的值。每当对 String 进行修改时,都会创建一个新的 String 对象。。
2、StringBuilder 类型是可变的(mutable),它是非线程安全的。它可以动态地添加、删除或替换字符串中的字符。
3、StringBuffer 类型也是可变的,与 StringBuilder 类型类似,但它在方法上加了synchronized锁,是线程安全的。由于 StringBuffer 对方法进行了同步处理,因此在多线程环境中使用 StringBuffer 可以保证数据的一致性。
2、代码解释
  • String

public class dome {
    public static void main(String[] args) {
        // 1. String
        String str1 = "Hello";
        String str2 = str1.substring(1);
        String str3 = str2 + " World";

        System.out.println("str1: " + str1); 
        System.out.println("str2: " + str2);
        System.out.println("str3: " + str3);

        System.out.println("str1 == str2: " + (str1 == str2));
        System.out.println("str1 == str3: " + (str1 == str3));
        System.out.println("str2 == str3: " + (str2 == str3));

/*
        输入结果:
            str2: ello
            str3: ello World
            str1 == str2: false
            str1 == str3: false
            str2 == str3: false 
   
        这个示例中,我们定义了三个字符串变量 str1、str2 和 str3,并对它们进行一系列操作。
    具体来说,我们首先使用 substring() 方法从 str1 中获取子字符串 str2,然后将 str2 和
    另一个字符串 " World" 进行拼接,得到新的字符串 str3。
        接着,我们输出了三个字符串变量的值,并使用 == 运算符比较它们之间的关系。注意,这里
    使用 == 运算符比较的是两个字符串变量的引用地址是否相同,而不是它们所包含的字符序列是否
    相同。
        因为字符串是不可变的,所以当我们对字符串进行修改时,实际上是创建了新的字符串对象。
    从输出结果可以看出,虽然 str1、str2 和 str3 中包含的字符序列有重叠部分,但它们在内存
    中是完全独立的对象,它们的引用地址并不相同。这就证明了当我们对字符串进行修改时,Java 确
    实会创建新的字符串对象。
*/
    }
}
  • StringBuilder

public class dome {
    public static void main(String[] args) throws InterruptedException {
        //2.StringBuilder
        StringBuilder sb1 = new StringBuilder("Hello");
        sb1.append(" World");
        System.out.println(sb1.toString()); // "Hello World"

        //验证非线程安全
        StringBuilder sb2 = new StringBuilder();
        //创建线程一
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sb2.append("1");
            }
        });
        //创建线程2
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sb2.append("2");
            }
        });
        //开启线程
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(sb2.toString());

/*
        在这个案例中,我们创建了一个StringBuilder对象,然后启动了两个线程。每个线程都向
    StringBuilder中追加1000个字符,一个是"1",一个是"2"。最后,我们将结果打印到控制台上。
    如果StringBuilder是线程安全的,那么我们期望最终结果应该是1000个"1"和1000个"2",并且
    它们的顺序可能是交错的。但实际上,由于StringBuilder不是线程安全的,我们很可能得到不同
    的结果,在这种情况下,输出的字符串可能是由1000个"1"和一些"2"组成,或者是由1000个"1"和
    一些"2"组成,或者是一个混合的字符串。
*/
    }
}
  • StringBuffer

public class dome {
    public static void main(String[] args) throws InterruptedException {
        //2.StringBuffer
        StringBuffer sb2 = new StringBuffer();
        //验证线程安全
        //创建线程一
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sb2.append("1");
            }
        });
        //创建线程2
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                sb2.append("2");
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(sb2.toString());
    }
}
/*
        在这个案例中,我们创建了一个StringBuffer对象,然后启动了两个线程。每个线程都向
    StringBuffer中追加1000个字符,一个是"1",一个是"2"。最后,我们将结果打印到控制台上。
    如果StringBuffer是线程安全的,那么我们期望最终结果应该是1000个"1"和1000个"2",并且
    它们的顺序可能是交错的。但实际上,无论我们跑几次,结果都是我们预期的结果,所以
    StringBuffer是线程安全的。
*/
3、总结以及使用
  • String类:

每当需要更改字符串时,都会创建一个新的String对象,这可能会浪费大量的内存和时间。String适合用于以下情况:

  • 当字符串不需要被修改时;

  • 当需要将字符串作为参数传递给某个方法时,因为String对象是不可变的,所以不必担心在传递过程中被修改。

  • StringBuilder类:

StringBuilder类也用来存储字符串,但它是可变的。也就是说,可以通过调用方法来修改StringBuilder对象的值,而不必每次都创建一个新的对象。StringBuilder适合用于以下情况:

  • 当需要频繁地修改字符串时;

  • 当需要构建一个字符串时,可以使用append方法将多个字符串拼接在一起。

  • StringBuffer类:

StringBuffer类和StringBuilder类非常类似,都是可变的字符串,但是StringBuffer类是线程安全的,也就是说,它的方法都是同步的。这使得它适合在多线程环境中使用。StringBuffer适合用于以下情况:

  • 当需要在多个线程中共享可变的字符串时;

  • 当需要频繁地修改字符串时,但又需要线程安全性。

综上所述,如果你需要一个不可变的字符串对象,使用String类;如果你需要频繁修改字符串,或者需要构建一个字符串,使用StringBuilder类;如果你需要在多个线程中共享可变的字符串,或者需要频繁修改字符串并且需要线程安全性,使用StringBuffer类。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Robus_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值