为什么Java中字符串是不可变的


默认情况下,Java 字符串是不可变的。字符串的不变性有助于提供缓存、安全性、快速性能和更好的内存利用率等功能。本教程讨论字符串的不可变性如何帮助实现这些功能。

1. 什么是不可变类?

什么是不可变类? 让我们从不可变性本身开始。一个不可变对象是一个其状态在其整个生命周期内都保证不会发生改变的对象。这意味着一旦初始化了对象的状态,它就无法在任何情况下被改变。

Java也有不可变类,主要包括String和包装类。

2.字符串的运作方式

在Java中,内存被分为三个部分,即堆(Heap)、栈(Stack)和字符串常量池(String Pool)。字符串常量池是专门用于存储字符串字面值的特殊区域。

当我们创建一个字符串时,会在字符串常量池中搜索具有完全相同内容的String对象。如果找到一个现有的String对象,那么它的引用就会指向新变量,因此,实际上,现有对象也会被重用于新的字符串声明。这有助于减小因为存在多个具有相同内容的字符串而导致的内存使用量。

String str1 = "value";
String str2 = "value";
String str3 = "value";

上述程序创建了三个String类型的变量,它们都指向字符串常量池区域中的同一个对象。将来所有具有内容“value”的字符串都会指向堆中的同一对象,从而节省内存。

当我们修改一个字符串时,会在字符串常量池中创建一个新的带有修改内容的字符串。现有的对象永远不会被改变。

str3 = "test";

当没有引用变量指向字符串常量池中的字符串对象时,该对象将被垃圾回收。通过这种方式,一旦创建了一个字符串,它就永远不会被更改。

3.不可变字符串的优点

现在让我们了解一下上面讨论的不可变性如何在运行时有所帮助。

3.1. 应用程序和数据安全性

首先,毫无疑问最重要的原因是安全性。这不仅适用于我们的应用程序,甚至适用于JDK本身。Java类加载机制是根据传递的类名参数来工作的,然后在类路径中搜索这些类。

在以下程序中,我们通过类名加载SQL服务器驱动程序。想象一下,如果字符串是可变的,那么恶意操作者可以更改驱动程序名称,在运行时加载恶意驱动程序类,并几乎不费力地入侵应用程序。

public static final String DRIVER_CLASS = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(DRIVER_CLASS);

类似地,恶意操作者可以更改SQL语句并在运行时执行SQL注入攻击。不可变性确保不会发生此类修改。

3.2. 提高性能

String类的不可变性是字符串常量池的基础。如果没有不可变性,普通堆内存和字符串常量池之间就没有区别。

正如在前面的部分中讨论的那样,字符串常量池有助于实现更好的内存利用率,从而提高性能。

3.3. 线程安全性

不可变对象在多线程应用程序中自动具备线程安全性。如果某物无法更改,那么即使线程也无法更改它。非常简单!

由于String类在Java编程语言中是主要的构建块,因为它用于类加载机制,因此在多线程情况下,必须防止String类被污染。不可变性在这里起到了魔法作用。

3.4. 缓存

缓存通常是作为键-值对实现的,类似于Java中的Map实现。缓存键通常存储为字符串,以便快速查找。

考虑一下,如果我们可以在与其关联的值存储在缓存中之后更改键,那么在我们意外构建相同键之前,将不可能再检索该值。

字符串的不可变性保证了缓存键永远不会被更改。这就是为什么在Java中字符串是缓存和映射中最常用的键的原因。

结论

从以上讨论可以得出结论,字符串的不可变性有助于实现Java应用程序所需的安全性和性能。



雷克沙私密文件保存应用

Java 字符串常量池

获取更多资讯请加入交流群


    协助本站SEO优化一下,谢谢!
    关键词不能为空
评 论
更换验证码