为什么Java中的String类是不可变的?
String类是Java中的一个不可变类(immutable class)。
简单来说,不可变类就是实例在被创建之后不可修改。
在《Effective Java》 Item 15 中提到了为了使类成为不可变,需要遵循的五条规则:
不要提供任何会修改对象状态的方法。
保证类不会被扩展。
使所有的域都是final的。
使所有域都成为私有的。
确保对于任何可变组件的互斥访问。
不可变类有许多优点,不可变类比可变类更加易于设计、实现和使用,不容易出错,且更加安全。
下面来看一下Java把String类设计为不可变类的几个原因:
1. 由于字符串池的存在
字符串池(String Pool)是方法区中的一块存储空间,当创建一个字符串时,如果池中已经存在相同的字符串就会返回其引用,而不是在堆中创建一个新对象。(此处指的是字面量创建字符串,用new关键字创建的话,无论池中存不存在都会在堆中创建一个新对象)
String string1 = "abcd";
String string2 = "abcd";

如果字符串是可变的话,通过一个引用改变它的值,将会导致其他引用的值也同样改变,从而可能发生错误。
2. 缓存hashcode
Java中经常用到一个字符串的hashcode,例如在HashMap和HashSet中。不可变性保证同一个字符串对象的hashcode总是相同的,而在使用时不用考虑其是否发生改变。
这意味着不需要每次都计算一遍hashcode,使程序更加高效。
/** Cache the hash code for the string */
private int hash; // Default to 0
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";
在这个例子中,如果String是可变的话将破坏HashSet(集合中可能会包含重复元素)。
4. 安全性
在Java中String被用作许多方法的参数,例如网络连接,对文件的操作等等。
假如String不是不可变的,一个连接或文件将可能被改变,这会产生严重的安全隐患。
因为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. 不可变对象自然是线程安全的
不可变对象是线程安全的,它们可以被自由地共享,不要求同步。
不可变类的优势有很多,当然也有缺点,就是对于每个不同的值都需要一个单独的对象。
转载请注明原文链接:http://www.cnblogs.com/justcooooode/p/7514863.html
参考资料
《Effective Java》Item 15
https://www.programcreek.com/2013/04/why-string-is-immutable-in-java/
为什么Java中的String类是不可变的?的更多相关文章
- Java中的String为什么是不可变的?
转载:http://blog.csdn.net/zhangjg_blog/article/details/18319521 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那 ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- Java中的String为什么是不可变的? -- String源码分析
众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不能改变状态的意思是, ...
- Java中的String为什么是不可变的? — String源码分析
原文地址:http://www.importnew.com/16817.html 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为 ...
- 【转】Java中的String为什么是不可变的? -- String源码分析
什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不 ...
- (转)Java中的String为什么是不可变的? -- String源码分析
背景:被问到很基础的知识点 string 自己答的很模糊 Java中的String为什么是不可变的? -- String源码分析 ps:最好去阅读原文 Java中的String为什么是不可变的 什 ...
- 关于Java中的String类知识点小总结
Java中的String类知识点 前言 在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 如何创建字符串 最简单的方式 String str = "he ...
- Java 中的 String 真的是不可变吗?
我们都知道 Java 中的 String 类的设计是不可变的,来看下 String 类的源码. public final class String implements java.io.Seriali ...
- JAVA中的String类(详解)
Java.lang.String类是final类型的,因此不可以继承这个类.不能修改这个类.String是一个类不属于基本数据类型. 可以从源码中看到,String是一个final类型. String ...
随机推荐
- 匿名委托与Lambda表达式
通过使用匿名委托(匿名方法),使编程变得更加灵活,有关委托与匿名委托请参考我的前一篇Blog<委托与匿名委托>. 继续之前示例,代码如下: static void Main(string[ ...
- php 微信公众号+微商城开发 基于Thinkphp3.2框架开发
说明:本教程是自己自学+自己的理解+扩展(包括学习过程中遇到的一些问题) 参考教程:麦子学院--李忠益--http://www.maiziedu.com/u/70409/ 微盟: http://www ...
- C/C++遍历文件夹和文件
本方法可用于windows和linux双平台,采用C/C++标准库函数. 库函数 包含头文件 #include 用到数据结构_finddata_t,文件信息结构体的指针. struct _findda ...
- Google研究人员宣布完成全球首例SHA-1哈希碰撞!
2004年的国际密码讨论年会(CRYPTO)尾声,我国密码学家王小云及其研究同事展示了MD5.SHA-0及其他相关杂凑函数的杂凑碰撞并给出了实例.时隔13年之后,来自Google的研究人员宣布完成第一 ...
- linux shell 之在线文本编辑sed
sed命令 文件编辑 sed是一种文本编辑命令,通过终端读取文件数据到缓冲区,然后通过sed编辑文本,在输出到指定的文件,sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用 ...
- C / C++ 运行环境搭建教程
C / C++ 运行环境搭建教程 一.实验环境 本机操作系统:Windows 7 64位 虚拟机:VMware Workstation 12 pro 虚拟机操作系统:Linux CentOS 7 二. ...
- (转载)深入Java关键字this的用法的总结
在Java程序设计中经常会见到this的使用,this使得程序设计变得规范.简单.灵活.但是在使用过程中,在不同场 合它的含义并不完全相同,使用不当还会出现错误, 本文对this的几种用法和出现的问题 ...
- oracle数据块核心剖析
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp57 数据块(Oracle Data Blocks),本文简称为" ...
- poj 3613 floyd + 快速幂
题意:本题的大意就是问从S 到 T 经过边得个数恰为k的最短路是多少. 思路:对于邻接矩阵每一次floyd求的是每个点间的最短距离,则n次floyd就是每个点间n条路的最短距离(可以重复边); 但是由 ...
- web服务的三大主流架构
1.远程过程调用 2.服务导向架构 3.表述性状态转移 今天在自学Spring架构时貌似发现 rest的表现.与RPC方式的最大差别,SOA方式更加关注如何去连接服务而不是去特定某个实现的细节.而re ...