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 ...
随机推荐
- [ActionScript 3.0] 自定义右键菜单
将自定义右键菜单的一些属性和方法归纳到AddRightMenu.as,通过实例化此类,调用相关方法即可测试! package { import flash.display.Sprite; import ...
- nginx负载均衡监测节点状态
1. 安装nginx_upstream_check_module模块 我的实验环境是在/root 和 /application目录下都编译安装了nginx-1.6.3,然后在/root目录下建立一个文 ...
- ssh协议git利用ss代理
前言 不知道ss为何物的绕道 求帐号的绕道 这里只是亲测 ssh协议下的git, 如何判断是什么协议出门左拐 判断是否需要代理 我遇到的问题是: ssh_exchange_identification ...
- C# Directory和DirectoryInfo类(文件目录操作)
对目录操作例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- 动态树Link-cut tree(LCT)总结
动态树是个好玩的东西 LCT题集 预备知识 Splay 树链剖分(好像关系并不大) 动态树(Link-cut tree) 先搬dalao博客 什么是LCT? 动态树是一类要求维护森林的连通性的题的总称 ...
- [转] Spark快速入门指南 – Spark安装与基础使用
[From] https://blog.csdn.net/w405722907/article/details/77943331 Spark快速入门指南 – Spark安装与基础使用 2017年09月 ...
- Q438 找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100. 说明: ...
- kafka监控服务搭建
wget https://github.com/Morningstar/kafka-offset-monitor/releases/download/0.4.1/KafkaOffsetMonitor- ...
- $bzoj1021-SHOI2008\ Debt$ 循环的债务 $dp$
题面描述 \(Alice\).\(Bob\)和\(Cynthia\)总是为他们之间混乱的债务而烦恼,终于有一天,他们决定坐下来一起解决这个问题.不过,鉴别钞票的真伪是一件很麻烦的事情,于是他们决定要在 ...
- $bzoj1019-SHOI2008$ 汉诺塔 $dp$
题面描述 汉诺塔由三根柱子(分别用\(A\ B\ C\)表示)和\(n\)个大小互不相同的空心盘子组成.一开始\(n\)个盘子都摞在柱子\(A\)上,大的在下面,小的在上面,形成了一个塔状的锥形体. ...