不变模式

不变模式就是为了尽可能的去除并行中的同步操作,提高并行程序的性能,可以使用一种不可改变的对象,依靠对象的不变性,可以确保其在没有同步操作的多线程环境中依然始终保持内部状态的一致性和正确性。并且,不变模式通过回避问题而不是解决问题的态度来处理多线程并发访问控制。

不变模式的主要使用场景

  • 当对象创建后,其内部状态和数据不再发生任何变化。
  • 对象需要被共享,被多线程频繁访问。

不变模式的实现(保证当对象被创建后,不发生任何改变)

  1. 去除setter方法以及所有修改自身属性的方法。
  2. 将所有属性设置为私有,并用final标记,确保不能被修改
  3. 确保没有子类可以重载
  4. 有一个可以创建完整对象的构造函数

对于第四点,在创建对象时,必须指定完整的数据,因为创建后,就无法进行修改了

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关键字的作用,这就意味着:

  1. String中的数据只能在String对象被构建时赋值,之后就永远不能改变
  2. 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中的不变模式的更多相关文章

  1. Java的String中的subString()方法

    方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...

  2. Here String 中不该进行分词

    我们知道,在 Shell 中,一个变量在被展开后,如果它没有被双引号包围起来,那么它展开后的值还会进行一次分词(word splitting,或者叫拆词,分词这个术语已经被搜索引擎相关技术占用了)操作 ...

  3. C++string中有关字符串内容修改和替换的函数浅析

    1.assign() 原型: //string (1) basic_string& assign (const basic_string& str); //substring (2) ...

  4. 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接

    长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...

  5. Java-J2SE学习笔记-查找一个String中,subString的出现次数

    1.查找一个String中,subString的出现次数 2.代码 package Test; public class TestStringContain { public static void ...

  6. string中常用的函数

    string中常用的函数 发现在string在处理这符串是很好用,就找了一篇文章放在这里了.. 用 string来代替char * 数组,使用sort排序算法来排序,用unique 函数来去重1.De ...

  7. String 中的秘密

    Navigation:  数据类型相关 > Delphi 的字符及字符串 > [3] - String 中的秘密   //String 的指针地址及实际的内存地址 var str: str ...

  8. String中的==与Empty

    1.String中的==与Equals方法执行结果一样吗? 我们都知道对于引用类型"=="比较的是引用而不是具体的值,但c#中有一种神奇的叫做操作符重载的东西.官方对String类 ...

  9. Java 字符串比较,String 中的一些方法 == 和 equals 的详解

    "==" 是比较的是两个对象的内存地址,而equals方法默认情况下是比较两个对象的内存地址. 1.String str = "hello"  生成的字符串,首 ...

随机推荐

  1. php中常用的字符串格式化函数

    ltrim():从字符串左删除空格或其他预定义字符串 rtrim():从字符串的末端开始删除空白字符串或其它预定义字符 trim():从字符串的两端删除空白字符和其他预定字符 str_pad():把字 ...

  2. Linux入门(11)——Ubuntu16.04安装texlive2016并配置texmaker和sublime text3

    安装过程中需要调用 Perl 的模块 Digest::MD5 来检测 ISO 文件的完整性:升级过程中界面需要调用 Perl 的模块 Tk: sudo apt-get install libdiges ...

  3. 【Java学习笔记之三十四】超详解Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  4. 有序链表--Java实现

    /*有序链表--使用的是单链表实现 *在插入的时候保持按照值顺序排列 *对于删除最小值的节点效率最高--适合频繁的删除最小的节点 * */ public class MySortedLinkList ...

  5. 学习笔记TF052:卷积网络,神经网络发展,AlexNet的TensorFlow实现

    卷积神经网络(convolutional neural network,CNN),权值共享(weight sharing)网络结构降低模型复杂度,减少权值数量,是语音分析.图像识别热点.无须人工特征提 ...

  6. @RequestBody对象为空,异常Required request body is missing

    1.异常 org.springframework.http.converter.HttpMessageNotReadableException: Required request body is mi ...

  7. Django web框架篇:基础

    对于web开发者来说,socket是基础.因为Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 对于真实开发中的python web程序来说,一般会分为两 ...

  8. QT生成PDF文件

    QString temp=""; //m_File_Content_Text_Edit->selectAll(); QString t_File_Content = m_Fi ...

  9. Pick apples(大范围贪心,小范围完全背包)

    Pick apples Time Limit: 1000MS Memory Limit: 165536KB Submit Statistic Discuss Problem Description O ...

  10. HQL语法

    HQL:Hibernate Query Language HQL是完全面向对象的查询语言,因此可以支持继承和多态等特征. $下面介绍HQL语句的语法 1.from子句 from Person 表明从P ...