如果需要设计一个不可变类,尤其要注意其引用类型Field,如果其引用类型Field的类是可变的,就必须采取必要的措施来保护该Field所引用的对象不会被修改,这样才能创建真正的不可变类。

 class Name {
private String firstName;
private String lastName; public Name() {
} public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
} public void setFirstName(String firstName) {
this.firstName = firstName;
} public String getFirstName() {
return this.firstName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public String getLastName() {
return this.lastName;
} public String toString() {
//return getClass().getName() + "@" + Integer.toHexString(hashCode());
return getClass().getName() + "@[firstName=" + this.getFirstName() + ", lastName=" + this.getLastName() + "]";
}
} class Person1 {
private final Name name; public Person1(Name name) {
this.name = name;
} public Name getName() {
return this.name;
} public String toString() {
//return getClass().getName() + "@" + Integer.toHexString(hashCode());
return getClass().getName() + "@[name=" + this.getName() + "]";
}
} class Person {
private final Name name; public Person(Name name) {
// 设置name为临时创建的Name对象,该对象的firstName和lastName与
// 传入的name对象的firstName和lastName相同
this.name = new Name(name.getFirstName(), name.getLastName());
} public Name getName() {
// 返回一个匿名对象,该对象的firstName和lastName与
// 该对象里的name的firstName和lastName相同
return new Name(name.getFirstName(), name.getLastName());
} public String toString() {
//return getClass().getName() + "@" + Integer.toHexString(hashCode());
return getClass().getName() + "@[name=" + this.getName() + "]";
}
} public class PersonNameImmutableTest {
public static void main(String[] args) {
Name n1 = new Name("悟空", "孙");
Person1 p1 = new Person1(n1);
// Person对象的name的firstName值为“悟空”
System.out.println(p1.getName().getFirstName());
// 改变Person对象的name的firstName值
n1.setFirstName("八戒");
// 下面的输出为“八戒”,已经改变了原来的值“悟空”
System.out.println(p1.getName().getFirstName());
// 上面的运行结果说明,Person对象的name的firstName值已经被改变了,
// 这就破坏了设计Person类的初衷 //为了保持Person1对象的不可变性,必须保护好Person1对象的引用类型Field:name,
//让程序无法访问到Person1对象的name Field,也就无法利用name Field的可变性来改变
//Person1对象了。
//为此,我们将Person1类该为Person类使用即可。
Name n = new Name("悟空", "孙");
Person p = new Person(n);
// Person对象的name的firstName值为“悟空”
System.out.println(p.getName().getFirstName());
// 改变Person对象的name的firstName值
n.setFirstName("八戒");
// 这样,无论如何修改name的值,Person对象的name值不会改变,
// 以下输出依然为“悟空”
System.out.println(p.getName().getFirstName());
}
}

或者做如下修改:

将Name类的setter方法删除掉,这样Name类是不可变的类,Person1类也是不可变的类。

创建正真的Java不可变类的更多相关文章

  1. Java 不可变类

    Java 不可变类 immutable object 不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值. 如JDK内部自带的很多不可变类:Interger.Long和String等. * ...

  2. JAVA的可变类与不可变类

    转自: http://www.blogjava.net/hilor/articles/150610.html 可变类和不可变类(Mutable and Immutable Objects)的初步定义: ...

  3. 【转】Java的可变类与不可变类

    1.可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容. 不可变类:当你获得这个类的一个实例引 ...

  4. JAVA不可变类(immutable)机制与String的不可变性--非常好.

    JAVA不可变类(immutable)机制与String的不可变性 https://www.cnblogs.com/jaylon/p/5721571.html

  5. 创建Java不可变类

    不可变(immutable)类的意思是创建该类的实例后,该实例的Field是不可改变的,Java提供的8个包装类和java.lang.String类都是不可变类. 如果需要创建自定义的不可变类,可遵守 ...

  6. JAVA不可变类(immutable)机制与String的不可变性

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...

  7. 【Java基础】JAVA不可变类(immutable)机制与String的不可变性

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...

  8. JAVA不可变类与可变类、值传递与引用传递深入理解

    一个由try...catch...finally引出的思考,在前面已经初步了解过不可变与可变.值传递与引用传递,在这里再次深入理解. 1.先看下面一个try..catch..finally的例子: P ...

  9. Java不可变类与final类

    概念 Java的不可变类是指八个基础类型的包装类和String,他们的数据成员是不可变的.使用加法等操作时,其实是创建了一个新的对象. Java的final类是对类用关键字final进行修饰,说明该类 ...

随机推荐

  1. WINDOWS中设置计划任务执行PHP文件

    1.写一个PHP程序,命名为test.php,内容如下所示: <? $fp = fopen("test.txt", "a+"); fwrite($fp, ...

  2. High-level NavMesh Building Components

    Here we introduce four high level components for the navigation system: //这里我们介绍四个高水平导航系统组件: NavMesh ...

  3. 如何用ChemDraw选择结构

    在使用ChemDraw软件过程中,我们往往会需要对结构进行翻滚.连结.旋转.分解.组合等操作.但是对于新手用户来说不是每种操作大家都会使用的. 针对这种情况我们会有一系列的教程来为大家讲解.下面我们就 ...

  4. php7 宏杂记

    php.h                                 zend_api.h ZEND_FN(name) ---> zif_##name PHP_FUNCTION(name) ...

  5. HttpServletRequest和HttpServletResponse简介

    http://blog.csdn.net/tong_xinglong/article/details/12972819

  6. iOS开发之--去除按钮的点击效果

    Button.adjustsImageWhenHighlighted = NO; 去除按钮的点击效果,用这句代码就可以了!

  7. Docker1.12 + Swarm 构建动态微服务应用

    导读 我们在之前提到过一个示例,即一款由前端与多项后端服务共同构成的微服务应用.其中前端为Traefik HTTP代理,负责将各项请求路由至后端服务.而后端则非常简单,是一套基于Go的HTTP Web ...

  8. 后Hadoop时代的大数据架构

    提到大数据分析平台,不得不说Hadoop系统,Hadoop到现在也超过10年的历史了,很多东西发生了变化,版本也从0.x进化到目前的2.6版本.我把2012年后定义成后Hadoop平台时代,这不是说不 ...

  9. [黑金原创教程] FPGA那些事儿《设计篇 II》- 图像处理前夕·续

    简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...

  10. github 's usage

    author:headsen  chen date: 2018-05-30   10:50:56 notice:This  article is created by headsen chen him ...