Java不可变对象string_为什么在Java中String是不可变的?

我们不能确定Java设计师在设计时实际上在想什么,String但只能基于从字符串不变性中获得的优势来总结这些原因,其中一些是

1.字符串常量池的存在

正如“ 为什么将字符串存储在字符串常量池中”一文中讨论的那样,每个应用程序都会创建太多的字符串对象,并且为了避免JVM首先创建大量的字符串对象,然后再进行垃圾回收,从而节省了JVM。JVM将所有字符串对象存储在称为字符串常量池的单独内存区域中,并重用该高速缓存池中的对象。

每当我们创建字符串文字时,JVM都会首先查看该文字是否已存在于常量池中,如果常量池中已经存在,新引用将开始指向SCP中的同一对象。

String a = "Naresh";

String b = "Naresh";

String c = "Naresh";

在与值上面的例子中的字符串对象Naresh将在SCP获得创建只有一次,所有参考a,b,c会如果我们试图在改变指向同一个对象,但什么a如a.replace("a", "")。

理想情况下,a应该有值Nresh,但是b,c应该维持不变,因为我们一直在变动中的最终用户a只。而我们知道a,b,c所有都指向同一个对象,因此,如果我们做出改变a,其他人也应反映这一变化。

但是字符串的不变性使我们避免了这种情况,并且由于字符串对象的不变性,字符串对象Naresh永远不会改变。因此,当我们进行任何更改a而不是更改字符串对象时,NareshJVM都会创建一个新对象,将其分配给该对象a,然后在该对象中进行更改。

因此,仅由于String的不可变性,才可能使用String池,并且如果String不能保持不变,则缓存字符串对象并重新使用它们是不可能的,因为任何变量都会更改值并破坏其他变量。

这就是为什么它非常特殊地由JVM处理并被赋予一个特殊的内存区域的原因。

2.线程安全

当多个线程在一个对象上运行时,一个对象被称为线程安全的,但是它们中的任何一个都无法破坏其状态,并且对象在任何时间点都为每个线程保持相同的状态。

由于我们创建一个不可变对象后,任何人都无法对其进行修改,这使得每个不可变对象默认情况下都是线程安全的。我们不需要对其应用任何线程安全措施,例如创建同步方法。

因此,由于字符串对象具有不变性,因此它可以被多个线程共享,即使它被多个线程操纵,它也不会改变其值。

3.安全性

在每个应用程序中,我们都需要传递几个秘密,例如用户的用户名\密码,连接URL,并且通常,所有这些信息都作为字符串对象传递。

现在假设如果String本质上不是一成不变的,那么它将对应用程序造成严重的安全威胁,因为允许更改这些值;如果允许,则由于错误的代码编写或任何其他人可能会更改这些值。可以访问我们的变量引用。

4.类加载

如在Java中使用反射通过示例创建对象中所讨论的,我们可以使用Class.forName("class_name")方法将类加载到内存中,该类再次调用其他方法来这样做。甚至JVM也使用这些方法来加载类。

但是,如果您清楚地看到所有这些方法都将类名作为字符串对象接受,那么在Java类加载中使用Strings,并且不可变性提供了安全性,可以通过加载正确的类ClassLoader。

假设如果String不会是不变的,并且我们尝试加载将java.lang.Object其更改为org.theft.OurObject两者之间的值,那么现在我们所有的对象都有一种行为,可以使某人对不需要的事物使用。

5. HashCode缓存

如果要对任何对象执行任何与哈希相关的操作,则必须重写该hashCode()方法,并尝试使用对象的状态生成准确的哈希码。如果对象的状态正在更改,这意味着其哈希码也应更改。

因为String是不可变的,所以一个字符串对象持有的值永远不会改变,这意味着其哈希码也不会改变,这使String类有机会在对象创建期间缓存其哈希码。

是的,String对象在创建对象时会缓存其哈希码,这使其成为与哈希相关的操作的理想选择,因为不需要再次计算哈希码,这可以节省一些时间。这就是为什么String主要用作HashMap键的原因。

阅读有关Java中为什么String是不可变且最终的更多信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值