String、StringBuild、StringBuffer三者详解及区别

文章详细介绍了Java中的String类,包括其不可变性、创建方式以及如何通过构造函数和直接赋值创建对象的区别。此外,还讨论了通过equals和hashCode方法比较字符串以及如何通过字符串拼接改变值。接着,文章转向可变的StringBuilder和StringBuffer类,强调它们在多线程环境和性能优化中的应用,并解释了它们与String类的主要区别。最后,提到了字符串对象之间的转化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.String类

String是字符串常量,如果有去看它底层的人都知道,它的底层是由final修饰,所以其值明面上是不可变的序列,可能会有很多人开始疑惑了,没事,等我接下来一一细说

1.1String类创建有俩种方式:

(1)通过构造对象创建

String 变量名 = new String(有参/无参);

(2)通过直接赋值创建

String s1="abc";

这俩者的区别就在于内容相同时,地址不相同,我们先说通过构造对象创建

首先,这个图的结果是false 即俩个s1和s2地址不相同。首先String s1 = new String("abc"); 是创建了新的对象,即会在内存中申请一个空间,接着先在常量池中存放了"abc"这个对象,然后在去堆内存中存放一个"abc"对象。所以有参构造方法在jvm中就创建了俩个对象相比直接赋值会多出一个对象。而String s2 = new String("abc");也会在内存中申请一个新的空间,用于存放"abc"。
所以通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同

接着我来说一下通过直接赋值创建

老样子,我们先说结果为true,即s3和s4的地址相同。在直接将"abc"赋值给到了s3,内存中的堆内存就存放了"abc"这个字符串 而指向了地址(001),栈内存中放着 String s3 (001),当想要通过"abc"字符串赋值给s4时,在堆内存中找到了"abc"这个字符串,并将地址值传回到栈内存中存放的String s4。
所以通过直接赋值创建的方法,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象。

1.2String类 字符串的比较

上面我用到了地址比较是"==",有人说,这不是比较内容的嘛,怎么变成比较值了?

其实"=="对于基本数据类型时,比较的确实是对应内容,而对于引用数据类型时,它用来比较地址值,而引用数据类型用什么来比较值呢?

equals

当要比较俩个字符串是否相同时就可以用equals 如s1.equals(s2)

1.3String类 值的改变

我想这是很多人都迫切想知道的。String类被final修饰,那它如何改变其值?

1.字符串拼接

String a="a”;
String b="b";
a=a+b;
System.out.println(a);

答案是:ab

String可以做字符串拼接,从成改变a的值。但明面上我们看到了它改变的自己的值,但是暗地里它连自己都改变了,我们来看一段代码

        String a="a";
        String b="b";
        System.out.println(a.hashCode());
        a=a+b;
        System.out.println(a);
        System.out.println(a.hashCode());
答案是
97
ab
3105

可以发现,俩次a的值都不一样。原理就是String a="a";在栈内存中存放了 String a 及地址值001,在堆内存中存放了"a",而在a=a+b;时,堆内存中的"a"和旧地址就会被清除出堆内存,进来了 a+b的结果,即"ab",然后有了新的地址,在赋予String类的a的新地址

2.反射改变String的值

        String s = "abc";
        Class<? extends String> aClass = s.getClass();
        Field value = aClass.getDeclaredField("value");
        value.setAccessible(true);
        char[] b=(char[]) value.get(s);
        System.out.println(s);//输出原有的值
        System.out.println(s+"的hashcode=    "+s.hashCode());//原有值的地址
        b[0]='A';//原有字符串第一位改为A
        System.out.println();
        System.out.println(s+"的hashcode=    "+s.hashCode());//改变值后的地址
        System.out.println(s);//改变后的值

答案
abc
abc的hashcode=    96354

Abc的hashcode=    96354
Abc

通过反射改变的原有字符串的值,但在哈希表的数值仍不变,则地址不变。

二.StringBuilder类

他是一种非线程安全的,StringBuilder的类的对象能够被多次的修改、并且不产生新的对象。

且运行速度快

2.1格式

StringBuilder ss = new StringBuilder(有参或者无参);

当直接传字符串变量,则是将String类转化为StringBuilder类

2.2append、resever

StringBuilder类有自己的字符串添加方法,和字符串反转方法

当单线程操作字符串缓冲区下操作大量数据 StringBuilder。

三.StringBuffer类

StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 ,且是一种线程安全的。

2.1StringBuffer格式

StringBuilder ss = new StringBuilder(有参或者无参);

有参即直接传字符串变量,将String类转化为StringBuffer

2.2sppend、insert

与String最大的区别就在于StringBuilder类值改变的可行,它有自己的添加方法append()、insert()

可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

2.3deleteCharAt (int index)

public StringBuffer deleteCharAt (int index)

删除指定位置的字符,并返回本身

四.String、StringBuilder、StringBuffer

4.1区别

String类的值,在一般意义上,是不可变的,大部分使用的是字符串拼接,这就使得每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间

所以一般字符串是不可变

StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 ,且线程是安全的。

StringBuilder是可变类,速度是最快的,但线程不安全。

4.2互相转化

        String a="a";
        StringBuffer sb1= new StringBuffer(a);//将String --->  StringBuffer
        sb1.append("bc");
        a=sb1.toString();//将StringBuffer --->  String
        System.out.println(a);
        String a1="a";
        StringBuilder sb2=new StringBuilder(a1);//将String --->  StringBuilder
        sb2.append("bcd");
        a1=sb2.toString();//将StringBuilder --->  String
        System.out.println(a1);

StringBuffer和StringBuilder转换为String类时都是通过toString方法。

而StringBuffer、StringBuilder都可以进行相应操作后在转换为String类

String类转换为StringBuffer和StringBuilder,则在创建对象时加入即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值