Java为什么把String设计成不可变的?
2017-09-26 17:21
267 查看
原文来自:Why String is immutable in Java?
这是来自Java和Android面试中经常被问的一道题目。在Java语言中,String是字符串常量,StringBuilder是字符串变量,为什么将String设计成不可变的(immutable)?
在Java里String类是不可变的,不可变类是一个不能被修改实例的类,实例创建时所有的信息都被初始化,并且不可被修改。这样的设计也有很多优点,本文从内存、同步和数据结构方面总结了为什么把String类设计成不可变的原因。
下面的代码只在堆中创建一个字符串对象:
示意图如下:
![](https://img-blog.csdn.net/20170926153300165?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ2VvZmZlcnlzdW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
如果String是可变的,用一个引用改变字符串将导致其他引用的值错误。
在String类中有如下代码:
在这个实例中,如果字符串是可变的,他将违背集合的设计(集合包含非重复元素)。当然,上面的示例仅仅用作演示用,在真正的字符串类中没有值字段。
示例如下:
当然,不同的使用场景体现出不可变特性的优势也不相同。大家可以回忆自己项目中的使用场景,多加思考这类问题。
这是来自Java和Android面试中经常被问的一道题目。在Java语言中,String是字符串常量,StringBuilder是字符串变量,为什么将String设计成不可变的(immutable)?
在Java里String类是不可变的,不可变类是一个不能被修改实例的类,实例创建时所有的信息都被初始化,并且不可被修改。这样的设计也有很多优点,本文从内存、同步和数据结构方面总结了为什么把String类设计成不可变的原因。
1、字符串常量池的需要
字符串常量池是一个特殊的存储区域。当创建字符串时,如果字符串已经存在于池中,则将返回现有字符串的引用,而不会创建新的对象。下面的代码只在堆中创建一个字符串对象:
String string1 = "abcd"; String string2 = "abcd";
示意图如下:
如果String是可变的,用一个引用改变字符串将导致其他引用的值错误。
2、HashCode缓存
在Java里存储一个字符串通常需要使用到HashCode值,例如,在一个HashMap或一个HashSet。一成不变可以保证HashCode的唯一性,不用考虑他的变化。这意味着不需要每次使用它的时候都计算HashCode,提高操作效率。在String类中有如下代码:
private int hash;//this is used to cache hash code.
3、促进使用其他对象
下面的程序我们具体说明:HashSet<String> set = new HashSet<String>(); set.add(new String("a")); set.add(new String("b")); set.add(new String("c")); for(String a: set) a.value = "a";
在这个实例中,如果字符串是可变的,他将违背集合的设计(集合包含非重复元素)。当然,上面的示例仅仅用作演示用,在真正的字符串类中没有值字段。
4、安全
字符串被广泛用于许多Java类的参数,比如网络连接、打开文件等等。如果字符串不是不可变的,连接或者文件的更改将会导致严重的安全威胁。他认为连接到一个机器,并不是。因为参数是字符串的,字符串可变会导致在反射中的安全问题。(不可变性使之能够在不同的线程间共享,同时确保线程安全,帮助使用者减少线程同步的开发工作)示例如下:
boolean connect(string s){ if (!isSecure(s)) { throw new SecurityException(); } //here will cause problem, if s is changed before this by using other references. causeProblem(s); }
5、不可变对象自然是线程安全的
因为不可变对象是不能被改变的,所以他们可以自由的共享多线程。这就消除了他们进行同步的要求。总结
总之,String被设计成不可变的是出于效率和安全的因素。这也是为什么很多情况下首选类是不可变类的原因。当然,不同的使用场景体现出不可变特性的优势也不相同。大家可以回忆自己项目中的使用场景,多加思考这类问题。
相关文章推荐
- JAVA基础之——为什么String要设计成不可变的?
- 为什么Java的String设计为不可变的?
- 为什么Java中的String是设计成不可变的?(Why String is immutable in java)
- 为什么Java中的String设计成不可变的?
- Java基础——为什么Java中的String设计成不可变的?
- 【String】为什么 Java 要把字符串设计成不可变的
- Java 中的 String 为什么是不可变的? 基础知识要扎实
- 【Java学习笔记】 String变量为什么是不可变的?
- 为什么String要设计成不可变的?
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? — String源码分析
- Java中的String为什么是不可变的
- 为什么在java中String是不可变的?
- 为什么java中的String要设计成不能改变的类型
- 为什么Java要把字符串设计成不可变的
- 为什么String要设计成不可变的?
- Java中String为什么被设计成immutable(不可修改的)/final
- JAVA String的不可变设计(结合源码)
- (转)Java中的String为什么是不可变的