关于String中的不变模式
不变模式
不变模式就是为了尽可能的去除并行中的同步操作,提高并行程序的性能,可以使用一种不可改变的对象,依靠对象的不变性,可以确保其在没有同步操作的多线程环境中依然始终保持内部状态的一致性和正确性。并且,不变模式通过回避问题而不是解决问题的态度来处理多线程并发访问控制。
不变模式的主要使用场景
- 当对象创建后,其内部状态和数据不再发生任何变化。
- 对象需要被共享,被多线程频繁访问。
不变模式的实现(保证当对象被创建后,不发生任何改变)
- 去除setter方法以及所有修改自身属性的方法。
- 将所有属性设置为私有,并用final标记,确保不能被修改
- 确保没有子类可以重载
- 有一个可以创建完整对象的构造函数
对于第四点,在创建对象时,必须指定完整的数据,因为创建后,就无法进行修改了
eg:
public final class Book {
private final String name;
private final String ID;
public Book(String name,String ID) {
this.name=name;
this.ID=ID;
}
public String getName() {
return name;
}
public String getID() {
return ID;
}
}
在不变模式中,final关键字起到了重要的作用。
- 对属性的final定义确保所有数据只能在对象被构造时赋值一次,之后,就永远不发生改变。
- 对class 的final确保了类不会有子类
注:根据里式原则,子类可以完全的替代父类。如果父类是不变的,那么子类也必须是不变的,但实际上为了防止子类做出一些意外的行为,这里干脆就把子类禁用了
关于String中的不变模式
在JDK中,不变模式有很多应用,如Integer,Long等所有元数据类的包装类,当然,最典型的就是String类了。
对于String类而言,内部是这样定义的:public final class String 是一个被final关键字修饰的类,我们来看看上面说到final关键字的作用,这就意味着:
- String中的数据只能在String对象被构建时赋值,之后就永远不能改变
- String类不会有子类重载它的方法,也确保了String类生成的对象就是String对象,而不可能是其他类的对象
为什么String要被设计成不变模式呢?
很明显,当然是为了安全呀
先看到String源码中的如何赋值的
/** The value is used for character storage. */
private final char value[];
注释部分说的很明白,它是用一个final的字符数组来储存字符串的。
虽然value是不可变,但只是value这个引用地址不可变。但是Array数组是可变!!!
因为Array变量只是stack上的一个引用,数组的本体结构在堆。如图:

String类里的value用final修饰,只是说stack里的这个叫value的引用地址不可变。没有说堆里array本身数据不可变。
eg:
final char value[]={'a','b','c'};
char value2[]={'d'};
//value=value2; //编译器报错,因为用了final修饰
value[0]='d';
for (char v : value) {
System.out.print(v);//输出 dbc
}
很明显,这个value虽然被声明成final,但是如果value溢出了,就很容被修改了。
幸好,在设计String 的时候,value不仅是final的,而且还是private的,并且在后面所有String的方法里很小心的没有去动Array里的元素,没有暴露内部成员字段。
再者,String基本约定中最重要的一条是immutable。String是几乎每个类都会使用的类,所以保护String的不可变很重要,所以整个String类被设成final,从而实现禁止继承,避免被其他人继承后破坏。
假如String没有声明为final, 那么String的子类就有可能是被复写为mutable的,这样就打破了成为共识的基本约定。并且会造成不可想象的后果,
如,Hashmap之类的集合的key值,mutable的String有非常大的风险,可能会破坏了Hashmap键值的唯一性等。
安全之外,还可以涉及到性能方面:
String在堆中维护着一个字符串常量池。如字符串one和two都赋值为"something"。它们其实都指向同一个内存地址。
String one = "someString";
String two = "someString";

这样在大量使用字符串的情况下,可以节省内存空间,提高效率。
More:
Why String is Immutable or Final in Java?
关于String中的不变模式的更多相关文章
- Java的String中的subString()方法
方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...
- Here String 中不该进行分词
我们知道,在 Shell 中,一个变量在被展开后,如果它没有被双引号包围起来,那么它展开后的值还会进行一次分词(word splitting,或者叫拆词,分词这个术语已经被搜索引擎相关技术占用了)操作 ...
- C++string中有关字符串内容修改和替换的函数浅析
1.assign() 原型: //string (1) basic_string& assign (const basic_string& str); //substring (2) ...
- 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接
长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...
- Java-J2SE学习笔记-查找一个String中,subString的出现次数
1.查找一个String中,subString的出现次数 2.代码 package Test; public class TestStringContain { public static void ...
- string中常用的函数
string中常用的函数 发现在string在处理这符串是很好用,就找了一篇文章放在这里了.. 用 string来代替char * 数组,使用sort排序算法来排序,用unique 函数来去重1.De ...
- String 中的秘密
Navigation: 数据类型相关 > Delphi 的字符及字符串 > [3] - String 中的秘密 //String 的指针地址及实际的内存地址 var str: str ...
- String中的==与Empty
1.String中的==与Equals方法执行结果一样吗? 我们都知道对于引用类型"=="比较的是引用而不是具体的值,但c#中有一种神奇的叫做操作符重载的东西.官方对String类 ...
- Java 字符串比较,String 中的一些方法 == 和 equals 的详解
"==" 是比较的是两个对象的内存地址,而equals方法默认情况下是比较两个对象的内存地址. 1.String str = "hello" 生成的字符串,首 ...
随机推荐
- jdk8 JAVA_OPTS
JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m -Djava. ...
- 【问题排查】fastjson线上排坑记
前言 版本上线时发现fastjson的toString方法的返回的字符串与与之前版本的toString方法返回的字符串不相同,这导致依赖toString进行md5计算所得到的结果不相同,更进一步导致其 ...
- vb.net 代码建立控件,并显示在窗体上
Dim lb As New Label lb.Text = "hello" lb.Top = 200 lb.Left = 100 ...
- Linux系列教程(九)——Linux常用命令之网络和关机重启命令
前一篇博客我们讲解了Linux压缩和解压缩命令,使用的最多的是tar命令,因为现在很多源码包都是.tar.gz的格式,通过 tar -zcvf 能完成解压.然后对于.zip格式的文件,使用gunzip ...
- CSS选择器汇总
id选择器 #id 类选择器 .class 标签选择器 div, h1, p 相邻选择器 h1 + p 子选择器 ul > li 后代选择器 li a 通配符选择器 * 属性选择器 a[rel= ...
- 用Python从零开始创建区块链
本文主要内容翻译自Learn Blockchains by Building One 本文原始链接,转载请注明出处. 作者认为最快的学习区块链的方式是自己创建一个,本文就跟随作者用Python来创建一 ...
- 默认权限umask、文件系统权限、特殊权限
第1章 权限相关错误 1.1 普通用户 ls /root/ /root 属于root 普通用户没有任何权限,所以无法查看 [oldboy@znix ~]$ ls /root/ ls: cannot ...
- c++学习笔记---03---从一个小程序说起2
从一个小程序说起2 要求:编写一个程序,要求用户输入一串整数和任意数目的空格,这些整数必须位于同一行中,但允许出现在该行中的任何位置.当用户按下键盘上的"Enter"键时,数据输入 ...
- alert 执行顺序问题
<p><span id="span1">Hello World!</span></p> <script type=" ...
- JavaScript系列----AJAX机制详解以及跨域通信
1.Ajax 1.1.Ajax简介 Ajax简介这一部分我们主要是谈一下ajax的起源,ajax是什么?因为这些是跟技术无关的.所以,大多细节都是一笔带过. Ajax的起源? Ajax一词源于2005 ...