Java 基础系列:不变性
1.1 定义
不可变类(Immutable Objects):当类的实例一经创建,其内容便不可改变,即无法修改其成员变量。
可变类(Mutable Objects):类的实例创建后,可以修改其内容。
Java 中八个基本类型的包装类和 String 类都属于不可变类,而其他的大多数类都属于可变类。
ps: 某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象,不可变对象一定是线程安全的。不可变对象很简单。他们只有一种状态,并且该状态由构造函数来控制。
需要特别注意的是,不可变类的不可变是指该类的实例不可变而非指向该实例的引用的不可变。
1.2 充分条件
当满足以下条件时,对象才是不可变的:
(1)对象创建以后其状态就不能改变;
(2)对象的所有域都是final类型;
(3)对象是正确创造的(在对象创建期间,this引用没有溢出)。
1.3 特征
一个不可变类的定义应当具备以下特征:
- 所有成员都是 private final 的
- 不提供对成员的改变方法,例如:setXXXX
- 确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。
- 如果某一个类成员不是基本类型(primitive type)或不可变类,必须通过在成员初始化(in)或者getter方法(out)时通过深度拷贝(即复制一个该类的新实例而非引用)方法,来确保类的不可变。
- 如果有必要,重写hashCode和equals方法,同时应保证两个用equals方法判断为相等的对象,其hashCode也应相等。
1.4 优缺点
1. 优点:效率和安全。
- 效率(拷贝地址+缓存)
1. 当一个对象是不可变的,那么需要拷贝这个对象的内容时,就不用复制它的本身而只是复制它的地址,复制地址(通常一个指针的大小)只需要很小的内存空间,具有非常高的效率。同时,对于引用该对象的其他变量也不会造成影响。
2. 不变性保证了hashCode 的唯一性,因此可以放心地进行缓存而不必每次重新计算新的哈希码。而哈希码被频繁地使用, 比如在hashMap 等容器中。将hashCode 缓存可以提高以不变类实例为key的容器的性能。
线程安全
在多线程情况下,一个可变对象的值很可能被其他进程改变,这样会造成不可预期的结果,而使用不可变对象就可以避免这种情况同时省去了同步加锁等过程,因此不可变类是线程安全的。
2. 缺点:不可变类的每一次“改变”都会产生新的对象,因此在使用中不可避免的会产生很多垃圾。
Java 基础系列:不变性的更多相关文章
- Java基础系列-ArrayList
原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...
- 2015年12月28日 Java基础系列(六)流
2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流
- Java基础系列--static关键字
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...
- Java基础系列-Collector和Collectors
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...
- Java基础系列-二进制操作
原创文章,转载请标注出处:<Java基础系列-二进制操作> 概述 Java源码中涉及到大量的二进制操作,非常的复杂,但非常的快速. Java二进制表示法 首先了解下二进制,二进制是相对十进 ...
- Java基础系列-equals方法和hashCode方法
原创文章,转载请标注出处:<Java基础系列-equals方法和hashCode方法> 概述 equals方法和hashCode方法都是有Object类定义的. publi ...
- Java基础系列-Comparable和Comparator
原创文章,转载请标注出处:<Java基础系列-Comparable和Comparator> 一.概述 Java中的排序是由Comparable和Comparator这两个接 ...
- Java基础系列--HashMap(JDK1.8)
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10022092.html Java基础系列-HashMap 1.8 概述 HashMap是 ...
- 夯实Java基础系列1:Java面向对象三大特性(基础篇)
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...
- 夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!
目录 目录 string基础 Java String 类 创建字符串 StringDemo.java 文件代码: String基本用法 创建String对象的常用方法 String中常用的方法,用法如 ...
随机推荐
- IT兄弟连 HTML5教程 HTML5的靠山 RFC、WHATWG是什么WEB的新标准
RFC是什么 RFC文档也称请求注解文档(Requests for Comments,RFC),这是用于发布Internet标准和Internet其他正式出版物的一种网络文件或工作报告,内容和Inte ...
- 打开Github网站反应慢的问题
解决办法: 为了提高速度,可以使用HOSTS加速对Github网站加载的资源网站域名解析. 具体做法: 修改 C:\Windows\System32\drivers\etc 中的hosts文件(P ...
- 解决ie下vue列表数据不能即时刷新的问题
项目上要兼容IE浏览器(客户要求),发现之前在谷歌浏览器下,操作(增删改查)列表后列表能即时刷新(双向绑定),IE下却不行. 自己调试一下发现,在IE11下,如果GET请求请求相同的URL,默认会使用 ...
- C# 局部类/方法
没怎么用过的东西. 算是比较神奇的东西(见识短[笑]). 关键字是partial 如果在类应用关键字,则是局部类. 如果在方法应用关键字,则是局部方法. 局部类理解差不多就是一个东西分开了,但是还是一 ...
- 错误InnoDB:Attemptedtoopenapreviouslyopenedtablespace.
2013-08-04 13:48:22 760 [ERROR] InnoDB: Attempted to open a previously opened tablespace. Previous t ...
- [反汇编]函数开始部分利用mov ebx,esp找到返回地址(_KTRAP_FRAME结构)
我们理解call原理,首先将返回地址压入栈中,之后执行调用. 因此,在一个函数开始部分,esp依旧是上一个栈帧的esp,此时esp指向返回地址. 这就意味着使用 mov ebx,esp,之后 [ebx ...
- java高并发系列 - 第4天:JMM相关的一些概念
JMM(java内存模型),由于并发程序要比串行程序复杂很多,其中一个重要原因是并发程序中数据访问一致性和安全性将会受到严重挑战.如何保证一个线程可以看到正确的数据呢?这个问题看起来很白痴.对于串行程 ...
- U8 BOM数据结构
U8 BOM涉及的数据表有四张 bom_bom BOM资料 该表主要记录BOM表的一些基本信息,版本.创建.审核等信息,不包括任何子件.母件信息:bomid是BOM主键 bom_parent ...
- 1.springMVC Controller配置方式
一.手动配置方式 1.web.xml中DispatcherServlet控制器的的配置 SpringMVC也是一种基于请求驱动的WEB框架,并且使用了前端控制器的设计模式.前端控制器就是Dispatc ...
- Winform中设置ZedGraph的X轴的刻度根据曲线获取
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...