String的常量池和String不可变

本文深入探讨了Java中字符串常量池的概念及其如何影响String对象的创建与比较。解析了直接赋值与new String的区别,以及如何利用intern()方法避免重复对象的创建,节省内存空间。同时,阐述了字符串不可变性的原因及其带来的好处。

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

字符串常量池

String str1 = "hh";
String str2 = "hh";
String str3 = "hh";
System.out.println(str1 == str2);//true
System.out.println(str2 == str3);//true

我们应该知道String是一个引用类型,str1 str2 str3 内存储的是这个"hh"的地址,这就说明了str1 str2 str3 指向了同一个对象。也就说str2 str3 在堆内没有创建一个新的内存空间. 实际上在jvm的底层实际会自动维护一个对象池,也就是字符串常量池

如果采用了直接赋值的模式进行对String类的对象进行实例化对象,那木这个字符串内容,会直接保存在这个对象池中.
如果下次直接使用直接赋值模式申明String类对象,此时的对象池中如果有这个内容,将直接进行引用,如果没有,开辟新的字符串对象后将其保存在对象池中以供下次使用.

========================================================

String str1 = "hh";
String str2 = new String("hh");

System.out.println(str1 == str2);//false

而若是用上述这个方法来创建一个新的String类,就会再次开辟一个堆内存空间,也就是会同时有两个堆内存空间来存储这个相同内容的字符串.比较浪费存储空间.
因此我们引用intern()来解决这个问题

String str1 = "hh";
String str2 = new String("hh").intern();

System.out.println(str1 == str2);//true

这种做法会让在使用String的构造方法的时候会在String对象池中查找是否有个内容的对象,如果有就会直接引用,若果没有则会在堆上直接开辟一个内存空间来存放这个内容,并且加在对象池中

字符串不可变

1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了.
2. 不可变对象是线程安全的.
3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.

String是一个类,内部是基于char[]来实现的,但是String类中并没有提供set方法来改变内部的字符数组.
我们按住ctrl+右键进入内部可以发现在这里插入图片描述
这个是char无法改变的,
当我们想修改一个字符串的时候,大多都是借助原来的字符串创建一个新的字符串.

String str1 = "hh";

str1 = "a" + str1.substring(1);
System.out.println(str1);
//ah

我们要是想直接在原来的字符串上进行修改,使用反射这种方法来破坏封装,访问一个内部的private成员来改变.

String str1 = "hh";

//获取String类中的value字段,这个value和String原码中的value是匹配的
Field valueField = String.class.getDeclaredField("value");//这个要处理异常
//将这个字段的访问属性设为true
valueField.setAccessible(true);
//把str1中的value属性获取到
char[] value = (char[]) valueField.get(str1);//这个也要处理异常
//修改
value[0] = 'a';
System.out.println(str1);//ah
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值