Java 不可变类
Java 不可变类
immutable object 不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。
如JDK内部自带的很多不可变类:Interger、Long和String等。
** 不可变类,指的是 该类的实例不可变,而非指向该实例的引用的不可变**
优点
- 线程安全
- 当一个对象是不可变的,那么需要拷贝这个对象的内容时,就不用复制它的本身而只是复制它的地址,复制地址(通常一个指针的大小只需要很小的内存空间,具有非常高的效率。同时,对于引用该对象的其他变量也不会造成影响。
- 此外,不变性保证了hashCode 的唯一性,因此可以放心地进行缓存而不必每次重新计算新的哈希码。而哈希码被频繁地使用, 比如在hashMap 等容器中。将hashCode 缓存可以提高以不变类实例为key的容器的性能。
如何实现
- 所有成员都是private final;
- 不提供改变成员的方法,setter ;
- 确保所有方法不会被重载, 使用final class 强不可变类,或 所有方法加上final;
- 如果一个类的成员,不是基本类型primitive type或不可变类, 则在成员初始化和 getter方法时,深度拷贝(复制类的实例而非引用);
- 如果有必要,重写hashCode equals, 应保证在equals相等时,hashCode也相等。
通过反射修改String 对象的值
//用反射获取 修改string 值;
public static void main(String[] args){
String s= "Hello World";
System.out.println(" s: "+s);
try {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
char[] vs = (char[]) value.get(s);
vs[5] = 'F';
System.out.println(" s after: "+ s);
}catch (Exception e){
e.printStackTrace();
}
}
如果需要设计一个不可变类,尤其要注意其引用类型Field,如果其引用类型Field的类是可变的,就必须采取必要的措施来保护该Field所引用的对象不会被修改,这样才能创建真正的不可变类。
class Name{
private String first;
private String last;
public Name(){}
public Name(String f, String l){
first = f;
last = l;
}
public void setFirst(String first) {this.first = first;}
public String getFirst() {return first;}
public String getLast() {return last;}
public void setLast(String last) {this.last = last;}
@Override
public String toString() {
return "Frist: "+first + " last: " + last;
}
}
class Person{
private final Name name;
public Person(Name name){
this.name = new Name(name.getFirst(),name.getLast());
}
public Name getName() {
return new Name(name.getFirst(),name.getLast());
}
@Override
public String toString() {
return getClass().getName() + "@[name="+this.getName() +"]";
}
}
public class ImmutableTestTwo {
public static void main(String[] args){
Name n1 = new Name("悟空", "孙");
Person p1 = new Person(n1);
System.out.println(p1.getName().getFirst());
n1.setFirst("八戒");
System.out.println(p1.getName().getFirst());
}
}
或者做如下修改:
将Name类的setter方法删除掉,这样Name类是不可变的类,Person类也是不可变的类。
参考资料
从final的作用剖析String被设计成不可变类的深层原因
Java 不可变类的更多相关文章
- JAVA不可变类(immutable)机制与String的不可变性--非常好.
JAVA不可变类(immutable)机制与String的不可变性 https://www.cnblogs.com/jaylon/p/5721571.html
- JAVA的可变类与不可变类
转自: http://www.blogjava.net/hilor/articles/150610.html 可变类和不可变类(Mutable and Immutable Objects)的初步定义: ...
- JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...
- JAVA不可变类与可变类、值传递与引用传递深入理解
一个由try...catch...finally引出的思考,在前面已经初步了解过不可变与可变.值传递与引用传递,在这里再次深入理解. 1.先看下面一个try..catch..finally的例子: P ...
- 【Java基础】JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...
- 创建Java不可变类
不可变(immutable)类的意思是创建该类的实例后,该实例的Field是不可改变的,Java提供的8个包装类和java.lang.String类都是不可变类. 如果需要创建自定义的不可变类,可遵守 ...
- 【转】Java的可变类与不可变类
1.可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容. 不可变类:当你获得这个类的一个实例引 ...
- Java不可变类与final类
概念 Java的不可变类是指八个基础类型的包装类和String,他们的数据成员是不可变的.使用加法等操作时,其实是创建了一个新的对象. Java的final类是对类用关键字final进行修饰,说明该类 ...
- 创建正真的Java不可变类
如果需要设计一个不可变类,尤其要注意其引用类型Field,如果其引用类型Field的类是可变的,就必须采取必要的措施来保护该Field所引用的对象不会被修改,这样才能创建真正的不可变类. class ...
随机推荐
- LAMPer 技能树
- css3中的translate,transform,transition的区别
translate:移动,transform的一个方法 通过 translate() 方法,元素从其当前位置移动,根据给定的 left(x 坐标) 和 top(y 坐标) ...
- Vs.net 常用命令行
下面的是从 devenv /? 看到的 用法: devenv [解决方案文件 | 项目文件 | 任意文件.扩展名] [开关] devenv 的第一个参数通常是一个解决方案文件或项目文件. 如果 ...
- 2016级算法第一次练习赛-A.群鸦的盛宴
858 群鸦的盛宴 题目链接:https://buaacoding.cn/problem/858/index 思路 本题乍一眼看过去,你可能会想到使用一个二维数组A[51][51]来记录从i到j的路线 ...
- 手把手教你在CentOS 7.4下搭建Zabbix监控(转)
Linux系统版本:CentOS 7.4 1.安装前需要先关闭selinux和firewall. 1.1 [root@zabbix ~]# vi /etc/selinux/config 将SELINU ...
- 键盘压缩背景,ios滚动不流畅,禁止遮罩层下面内容滚动
1.<!--防止软键盘压缩页面背景图片--> <script> const bodyHeight = document.documentElement.clientHeight ...
- logo back 日志 发送邮件
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!--<pr ...
- Angular material mat-icon 资源参考_Editor
ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...
- ACM-素数专题(持续更新)
埃拉托斯特尼筛法,或者叫埃氏筛法(听上去似乎很高大上的样子) #include<bits/stdc++.h> using namespace std; typedef long long ...
- 项目中git的使用
通常一个项目的开发周期相对较长,为了便于对过程中的项目版本进行管理,以及方便多人合作进行开发,常需要使用到版本管理控制软件,本篇介绍常用的版本控制器git,记之共享. 一.git是什么?有何特点? 用 ...