为什么String要设计成不可变的?
英文原:http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/
转自:http://blog.csdn.net/renfufei/article/details/16808775
这是一个老生常谈的话题. 在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将为各种原因做一个小结。
1. 字符串常量池的需要
字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
如下面的代码所示,将会在堆内存中只创建一个实际String对象.
- String s1 = "abcd";
- String s2 = "abcd";
示意图如下所示:
假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.
请思考: 假若代码如下所示,s1和s2还会指向同一个实际的String对象吗?
- String s1= "ab" + "cd";
- String s2= "abc" + "d";
也许这个问题违反新手的直觉, 但是考虑到现代编译器会进行常规的优化, 所以他们都会指向常量池中的同一个对象. 或者,你可以用 jd-gui 之类的工具查看一下编译后的class文件.
2. 允许String对象缓存HashCode
Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。
字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码. 在String类的定义中有如下代码:
- private int hash;//用来缓存HashCode
3. 安全性
String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。
假如有如下的代码:
- boolean connect(string s){
- if (!isSecure(s)) {
- throw new SecurityException();
- }
- // 如果在其他地方可以修改String,那么此处就会引起各种预料不到的问题/错误
- causeProblem(s);
- }
总体来说, String不可变的原因包括 设计考虑,效率优化问题,以及安全性这三大方面. 事实上,这也是Java面试中的许多 "为什么" 的答案。
为什么String要设计成不可变的?的更多相关文章
- String的内存模型,为什么String被设计成不可变的
String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...
- 为什么Java中的String是设计成不可变的?(Why String is immutable in java)
There are many reasons due to the string class has been made immutable in Java. These reasons in vie ...
- 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因
声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...
- String被设计成不可变和不能被继承的原因
String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了一个字符串池(String pool),这使得String成为了一个特别的类 ...
- String类为什么设计成不可变的
在Java中将String设计成不可变的是综合考虑到各种因素的结果,需要综合考虑内存.同步.数据结构以安全方面的考虑. String被设计成不可变的主要目的是为了安全和高效. 1)字符串常量池的需要 ...
- String类为什么被设计成不可变类
1.享元模式: 1.共享元素模式,也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素. 2.Java中String就是根据享元模式设计的,而 ...
- [2017-09-04]Abp系列——为什么值对象必须设计成不可变的
本系列目录:Abp介绍和经验分享-目录 这篇是之前翻备忘录发现漏了的,前阵子刚好同事又提及过这个问题,这里补上. 本文重点在于理解什么是值对象的不可变性. Abp的ValueObject以及EF的Co ...
- 为什么String被设计为不可变?是否真的不可变?
1 对象不可变定义 不可变对象是指对象的状态在被初始化以后,在整个对象的生命周期内,不可改变. 2 如何不可变 通常情况下,在java中通过以下步骤实现不可变 对于属性不提供设值方法 所有的属性定义为 ...
- Java为什么把String设计成不可变的(immutable)
在java中,String是字符串常量,可以从内存,同步机制,数据结构等方面分析 1:字符串中常量池的需要 String不同于普通基础变量类型的地方在于对象.java中的字符串对象都保存在字符串常量池 ...
随机推荐
- python【第二十一篇】Django模板继承、分页、cookie验证
1.模板继承 母版master.html {% block title %}{% endblock %}2 {% block table-cont %}{% endblock %} 子板 {% ext ...
- 使用EF6.0出现:CS0029 无法将类型“System.Data.Entity.Core.Objects.ObjectContext”隐式转换为“System.Data.Objects.ObjectContext”错误
这是因为EF6.0重构了一些命名空间后,和VS原有的实体数据模型模板不一致了(ObjectContext context = ((IObjectContextAdapter)dataContext). ...
- hdu 1827
强连通分量——tarjin算法: 这题的思路就是找出多少个出度为0的连通分量,结果就是这些连通分量的元素的最小值相加: 一道很简单的题,改了我好久,= =!~ 贴代码: #include<cst ...
- Web API路由与动作(三)
本章包括三个小节 如果你输入了mvc的路由规则 这个可以粗略过一遍即可 内容说明有点繁琐 原文地址:http://www.asp.net/web-api/overview/web-api-rout ...
- 使用Java正则表达式的分组解析身份证的年月日
根据Java的Pattern和Matcher类通过分组解析出身份证的年月日: public class GetDateInIdCard { public static void main(String ...
- CKFinder 2.4 ASP.NET 破解
网上的破解教程对于2.4版本来说已经过时了. 以下是CKFinder 2.4 ASP.NET的亲测可用破解方法,经测试,只需修改两处代码. 打开ckfinder.js, 步骤1. 搜索替换如下代码: ...
- Java Entry使用
参考: http://blog.csdn.net/sunmenggmail/article/details/8952712 http://www.cnblogs.com/fstang/archive/ ...
- redhat下升级gcc编译器
在有网络的环境下,采用下载gcc源码进行编译的方式升级gcc版本,所以需要本身已有gcc编译器. 获取 gcc-4.9.2的包: wget http://gcc.skazkaforyou.com/re ...
- BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...
- 计算几何(凸包):SHTSC 2012 信用卡凸包
这道题是水题,发现平移某些边,答案就是圆心的凸包+一个圆的周长. 不要忽视精度误差! #include <algorithm> #include <iostream> #inc ...