为什么Java中的String是不可变的?(Why String is immutable o...

There are many reasons due to the string class has been made immutable in Java. These reasons in view, concurrency issues, security issues and performance issues. Here is a list of various valid reasons to go for immutable string class:

String在Java中被设计成不可变的是出于很多方面的考虑. 这么做主要是针对并发问题,安全问题和性能问题。下面列出了将String设计为不可变的各种原因:

同步

1. The use of immutability is a best practice and has been recommended by many sources including effective Java and official Oracle Java tutorials. The property of the object is that none of the member variables that object can be changed as they are marked as private and final. This property becomes an advantage in case of multi-threaded applications. Since the updating of the String object is not allowed, multiple threads cannot run in to synchronization issues which occur when one object updates the state of object while the other was reading the object.

1. “使用不可变的对象”是一个最佳实践,很多地方包括Effective Java(是一本书)和Oracle官方的教程都推荐使用这个准则. 不可变对象的所有成员变量都是不可变的,因为它们被设置成了private和final的. 在多线程环境中,这样的属性成了一个很大的优势. 由于对于String对象的修改操作是不允许的, 多线程环境中就不会遇到同步的麻烦,比如:一个线程正在更新数据而另一个线程正在读取数据.

The official Oracle Java tutorial says that developers should not have any doubt by using immutability. Usually developers think that by having immutability the number of objects in the memory will increase because instead of updating an object, a new object has to be created. But in reality this is balanced off by the reduction in garbage collector execution. If properly used immutability can make an application more stable.

Oracle的官方教程说:开发人员在使用不可变对象的时候不应该有任何疑虑.通常开发者们会认为内存中不可变对象的数量会越来越多因为对于一个对象的更改并不是真正的修改该对象,而是产生新的对象. But in reality this is balanced off by the reduction in garbage collector execution. 在程序中正确地使用不可变对象反而会使应用更加稳定。

性能

2. The second reason why string class is immutable in Java is both a cause as well as effect of string being immutable. Strings in Java in implement the fly weight design pattern and the result is string literal pool. This literal pool has the property that if string literal is already present in the literal pool then it will be reused every-time a string reference variable is initialized to a string literal with the same characters.

2.字符串不可变的第二个原因也可以理解为是字符串不可变的结果。Java中字符串实现的是享元模式,这就导致了字符串缓冲池的出现,字符串缓冲池的特点就是,如果一个字符串字面量已经在缓冲池中存在了,那么每次当一个字符串引用比那辆使用相同的字面值初始化的时候,这个字面量都将被重复使用。

The requirement for having a string literal pool arises from the fact that string class is immutable in Java. Imagine a scenario where millions of string objects have been created with same characters just because the new operator always creates and returns a new instance of the class and we cannot modify a string object once it has been created. The above scenario will result in performance issues. To avoid these performance issue, string literal pool has been introduced in Java.

字符串缓冲池的产生也是基于String在Java中是不可变的这个事实。假设一个场景:数十万计的具有相同字符的字符串对象被创建,而这仅仅是因为new操作符总是创建并返回一个新的字符串实例,而且创建后的每个字符串都不能被修改。这样的场景下将导致性能问题。为了避免这些性能问题,Java就引入了字符串缓冲池。

Now let us see why string literal pool is a cause for making string class immutable in Java. Since the string literals have to be reused, updating the contents of these objects should not be allowed. Had updating of string literals been allowed, a string literal may not be reused because its contents have been changed by another reference variable.

现在让我们看看为什么字符串缓冲池也是促使String被设计成不可变的原因。既然字符串字面量可以被重复使用,那么对于字符串的修改也就是不被允许的。如果对于字符串字面量的修改是被允许的,那么字符串将不能再被重用因为它的内容已经被其他引用变量修改过了。

性能

3. The most used key object for hash map is the string object. Every time a string is referenced in hash based collections classes, it’s hash code is calculated. The hash code of string objects depends upon the characters contained in that string. If the characters of a string object were allowed to be changed, the hash code of that string object will change when the characters of the string change. By making string class immutable in Java, it has been insured that the hash code of string object will not change after the string object has been created in the memory. More over, this allows the hash code to be cached as a member variable. Once the hash code has been calculated for a string object and is told as the value of this internal member variable, the same can be returned next time without the need for performing any calculation.

3.在哈希Map中使用最多的Key值就是字符串对象。每次当一个字符串被基于Hash算法的集合类所引用的时候,它的Hash值都将被计算出来。Hash值的结果取决于包含在字符串中的各个字符。如果字符串中的字符可以被改变,那么字符串的Hash值也将随着字符的改变而改变。通过将String设计成不可变的,就保证了当字符串在内存中被创建之后,它的hash值就不会发生改变。这样就使得Hash值可以被作为成员变量缓存起来,一旦一个字符串对象的Hash值被计算出来,而且被作为字符串的内部变量,那么下一次需要使用Hash值的时候就可以无需进行额外的计算就返回同样的值。

安全

4. The security aspect of having the string class immutable in Java is that strings are used for file operations, memory management and network operations. If strings are allowed to be mutable, various properties could be changed in malicious ways.

4.在安全方面将String设计成不可变的原因就是String被用来进行文件操作,内存管理和网络操作。如果字符串可以被修改,那么很多属性都将可能被恶意修改。

简单

5. Another reason to make the string class mutable is the simplicity aspect. Though for beginners it is a learning curve to understand the behavior of string objects but once they understand, it is very easy to visualize the behavior of string objects in any particular scenario. Allowing the updating of string objects would have made it more complex to understand the behavior of strings.

5.另一个将String设计成不可变的原因就是出于简单方面的考虑。尽管对于初学者来说理解字符串对象的行为是比较有难度的,但一旦他们理解了,在任何特殊的场景下理解字符串对象的行为就变得很容易了。而将字符串设计成可变的将使得这个理解的过程更加复杂。

The point to note about the design decision is that the advantages of making string class immutable are more than not making it immutable.

注意:这样设计的原因就是String不可变比String可变具有更多的优势。

========个人总结=========

之所以将String设计成为Immutable的,这是由String的作用所决定的。

1.这样可以解决同步安全问题。

2.设计成不可变的就会导致性能下降,因为每次修改都将产生新的对象,而字符串缓冲池很好的解决了这个问题。

3.安全,因为很多操作都是以字符串作为参数的,字符串如果可以修改,那么在我们操作的过程中如果有人对字符串进行了修改,那么我们将得不到正确的结果。

参考资料:

(1)http://www.javaexperience.com/why-the-string-class-is-immutable/#ixzz2grdKUGIh

(2)http://javarevisited.blogspot.com/2010/10/why-string-is-immutable-in-java.html

时间: 2024-11-05 01:02:22

为什么Java中的String是不可变的?(Why String is immutable o...的相关文章

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

原文链接:https://www.programcreek.com/2013/04/why-string-is-immutable-in-java/ java字符串是不可变的.不可变类只是一个不能修改实例的类.实例创建时所有的信息都被初始化,并且信息不能被修改.不可变类有许多优点.本文总结了字符串为什么被设计成不可变的原因.这说明在记忆的角度不变性的概念,同步和数据结构. 1.字符串池的要求: 字符串池(字符串特定池)是方法区域中的一个特殊存储区域.当创建字符串时,如果字符串已经存在于池中,则将

JAVA中使用System类的 getProperties()和getProperty(String)取得当前系统的属性

一.描述 java中取得系统的属性的方法有两种: 1.可以使用System类中的方法:public static Properties getProperties()得到系统的各种属性, 该方法返回一个Properties类,这个类继承自Hashtable,在该类中定义了各种属性的键值对. 2.直接使用System.getProperty(String key)获取所需的系统属性. 实际上两者是等价的,System.getProperty(String key)方法内部调用了System类内部声

java中String类为什么不可变?

在面试中经常遇到这样的问题:1.什么是不可变对象.不可变对象有什么好处.在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型? 1.不可变对象,顾名思义就是创建后的对象不可以改变,典型的例子有java中的String类型. 2.相比于可变对象,不可变对象有很多优势: (1)不可变对象可以提高String Pool(字符串常量池)的效率和安全性.如果你知道一个对象是不可变动 ,那么需要拷贝的对象的内容时就不用复制它本身二只是复制它的地址,复制地址(通常一个指针的大小

Java中的不可变类

本文与个人博客 zhiheng.me 同步发布,标题: Java中的不可变类. 不可变类(Immutable Objects):当类的实例一经创建,其内容便不可改变,即无法修改其成员变量. 可变类(Mutable Objects):类的实例创建后,可以修改其内容. Java 中八个基本类型的包装类和 String 类都属于不可变类,而其他的大多数类都属于可变类. 与引用不可变的区别 需要特别注意的是,不可变类的不可变是指该类的实例不可变而非指向该实例的引用的不可变. String s = "ab

Java中char和String的相互转换

转自:http://blog.csdn.net/yaokai_assultmaster/article/details/52082763 Java中char是一个基本类型,而String是一个引用类型.有时候我们需要在它们之间互相转换. String转换为char 在Java中将String转换为char是非常简单的. 1. 使用String.charAt(index)(返回值为char)可以得到String中某一指定位置的char. 2. 使用String.toCharArray()(返回值为

Java中int和String互相转换的多种方法

1 如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([String],[int radix]); 2). int i = Integer.valueOf(my_str).intValue(); 注: 字串转成 Double, Float, Long 的方法大同小异. 2 如何将整数 int 转换成字串 String ? A. 有叁种方法: 1.) St

怎么又出错了?盘点java中最容易出现的错误。

现如今,java已经广泛应用各种软件开发领域.基于面向对象的设计,java屏蔽了诸如C,C++等语言的一些复杂性,提供了垃圾回收机制,平台无关的虚拟机技术,Java创造了一种前所未有的开发方式.所以,java对比其他程序语言更加受欢迎.因此,Java中的异常也是随时发生,下面我就列出了我认为的Java开发最容易出现的10个错误. 1.重复造轮子一个明显的错误就是Java程序员习惯性的忽略已经存在的大量的库.在你决定造一个轮子之间,我建议你试着先搜一下是否有已经存在库.例如日志方面,有logbac

日常总结の关于Java中的常量池技术

一.相关概念 什么是常量用final修饰的成员变量表示常量,值一旦给定就无法改变!final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池 简单讲解一下class文件的结构,开头的4个字节是class文件魔数,用来标识这是一个class文件,说白话点就是文件头,既:CA FE BA BE. 紧接着4个字节是java的版本号,这里的版本号是34,因为笔者是用jdk8编译的,版本号的高低和jdk版本的高低相对应,高版本可以兼容低版本,但低版本无法执

java中方法传值小知识解析

1.java语言参数之间只有值传递,包括按值调用和按引用调用. 一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值. 按值调用:包括八大基本数据类型都是按值调用.传值的时候,也就是说方法得到的是所有参数值的一个拷贝. 按引用调用:数组.对象.传值时候,传递的是引用地址的拷贝,但是都是指向同一个对象. 2.String是不可变类(final and Immutable) 下面给大家一个例子: public class Example{     String str=new