【Java SE】 String、StringBuffer和StringBuilder

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述

1. 字符串不可变性

String是一种不可变对象,即字符串中的内容是不可改变,它们的内容被创建好后,就不能被修改了!
为什么呢~

1.1 设计不可变

String类在设计时是不可改变,String类实现描述中已说明,以下来自JDK1.8String类的部分实现,如下图:
在这里插入图片描述
在这里插入图片描述
1)String类中的字符实际保存在内部维护的value字符数组中
2)String类被final修饰,表示String类不能被继承
3)value被final修饰,表示value自身的值不能改变,即不能引用其它字符数组,但其引用空间中的内容可以修改

1.2 修改字符串创建新对象

所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
字符串的不可变性,字符串中的内容是不可改变,如修改了则是创建了新对象,改变的是新对象

1.3 为什么字符串不可变

误区
认为字符串不可变是因为其内部保存字符的数组value被final修饰了,因此不能改变
这种说法是错误的,不是因为String类自身被final修饰,也不是因为其内部value被final修饰而不能被修改
正解
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但其引用对象中的内容可以修改,“看起来String可变”,其实创建了新对象!!!

public class Test17 {
    public static void main(String[] args) {
        final int array[] = {1,2,3,4,5};
        array[0] = 100;
        System.out.println(Arrays.toString(array));
        array = new int[]{7,8,9};
        // 编译报错:Error:(15, 9) java: 无法为最终变量array分配值
    }
}

在这里插入图片描述
由上述代码进一步理解:可以修改对象引用的内容,但是无法更改引用的指向!!!

1.4 String类设计不可变的好处

为什么String类要设计成不可变的呢~
原因有以下3点:

  1. 从字符串对象池来说,方便实现字符串对象池,如果 String 可变,对象池就需要考虑写时拷贝的问题,变得复杂
  2. 从线程安全角度来说,不可变对象是线程安全的
  3. 从缓存角度来说,不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap中

1.5 字符串的修改

以下这种方式不推荐使用!!!
原因效率极低,中间创建好多临时对象,空间的占用

public class Test {
    public static void main(String[] args) {
        String s = "hello ";
        s += "world!";
        System.out.println(s);
    }
}

打印结果如下:
在这里插入图片描述
在上述代码过程中,查看反编码,具体过程分析如下图:
在这里插入图片描述
StringBuilder的构造方法如下:
在这里插入图片描述
可想而知,如果放在循环体中这样修改字符串,中间会创建好多临时变量
注意】尽量避免直接对String类型对象进行修改,String类不能修改,所有的修改都会创建新对象,效率非常低
String类进行修改时,效率非常慢,所以需要尽量避免对String的直接使用修改,如果要修改建议尽量使用StringBuffer或者StringBuilder,接下来StringBuffer和StringBuilder闪亮登场!

2. 如何查看反编码?

上面的反编码是如何进行查看的呢?下面是保姆级教程!!!
步骤
1)首先运行该程序!!!
在这里插入图片描述
2)找到文件所在位置
在这里插入图片描述
3)找到字节码文件
进入到这个界面,我们需要找到.class文件,即字节码文件
在这里插入图片描述
在这里插入图片描述
4 )输入cmd
在这里插入图片描述
5)输入 javap -c Test15
在这里插入图片描述
注意事项】javap -c Test15中Test15是该程序的类名,请输入你自己的类名哦~

3. StringBuffer和StringBuilder

由于String的不可更改特性,为方便字符串的修改,Java中又提供StringBuilder和StringBuffer类这两大类,这两个类大部分功能是相同的
这里介绍 StringBuilder和StringBuffer常用的一些方法:
在这里插入图片描述
其它方法需要用到可参阅Java在线文档
以下为上述方法的具体使用,更深入了解其方法~

public class Test {
    public static void main(String[] args) {
            StringBuilder sb1 = new StringBuilder("hello");
            StringBuilder sb2 = sb1;
            //append追加即尾插(字符、字符串、整形数字)
            sb1.append(' ');                  //hello
            sb1.append("world");              //hello world
            sb1.append(1);                    //hello world1
            System.out.println(sb1);          //hello world1
            System.out.println(sb1 == sb2);   //true
            System.out.println(sb1.length());    //获取字符串的有效长度12
            System.out.println(sb1.capacity());  //获取底层数组的总大小
            sb1.setCharAt(0, 'H');     //设置任意位置的字符 Hello world1
            sb1.insert(0, "Hello world!!!");         //Hello world!!!Hello world1
            System.out.println(sb1);
            System.out.println(sb1.indexOf("Hello"));          //获取Hello第一次出现的位置
            System.out.println(sb1.lastIndexOf("hello"));  	   //获取hello最后一次出现的位置
            sb1.deleteCharAt(0);                               //删除首字符
            sb1.delete(0,5);                                   //删除[0, 5)范围内的字符
            String str = sb1.substring(0, 5);                  //截取[0, 5)区间中的字符以String的方式返回
            System.out.println(str);
            sb1.reverse();                      //字符串逆转
            str = sb1.toString();               //将StringBuffer以String的方式返回
            System.out.println(str);
    }
}

在很多题目中,StringBuilder.append()方法经常使用到,应用于那些经常要修改的字符串中,还是相当方便哒~
注意事项
String和StringBuilder类不能直接转换。如果想互相转换,采用如下原则:

String—>StringBuilder: 1)利用StringBuilder的构造方法 2) append()方法
StringBuilder—>String: 调用toString()方法

4. 常考面试题

String、StringBuffer、StringBuilder的区别

  1. 内容上,String的内容不可修改,StringBuffer与StringBuilder的内容可以修改
  2. 功能上,StringBuffer与StringBuilder大部分功能是相似的
  3. 线程安全上,StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作(其实需要具体代码具体分析,StringBuffer把关键方法都加了synchronized,但并不是说写了synchronized就一定是线程安全,此处就简要理解即可)

解释说明
对线程安全来说,StringBuffer线程安全,可以在多线程下使用,StringBuilder线程不安全在单线程下使用,那么都用StringBuffer不就好了嘛~不需要考虑线程安全问题了
不行!!!会浪费很多资源,加锁和释放锁都会浪费资源!
💛💛💛本期内容回顾💛💛💛
在这里插入图片描述✨✨✨本期内容到此结束啦~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值