如果需要设计一个不可变类,尤其要注意其引用类型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. C++ new delete操作符

    //new delete操作符 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; /* 1.n ...

  2. CSS旋转&翻转,兼容方案

    CSS代码,高级浏览器使用transform,ie用滤镜实现. 转自http://aijuans.iteye.com/blog/19364921 /*水平翻转*/ 2 .flipx { 3 -moz- ...

  3. (转)内核container_of(ptr,type,member) 解析

     container_of(ptr,type,member) 用于在已知结构体里面成员member和该成员指针ptr(就是地址)和结构体类型type, 返回该成员所在的结构体的指针(就是地址), 例如 ...

  4. before伪类的超有用应用技巧——水平菜单竖线分隔符

    方法一.li前面加before伪类 <!doctype html> <html dir="ltr" lang="zh-CN"> < ...

  5. php -- 用文本来存储内容,file_put_contents,serialize,unserialize

    根据存储的内容来划分 字符串: file_put_contents :将一个字符串写入文件 语法:int file_put_contents ( string $filename , mixed $d ...

  6. db2 将逗号分隔数据转换为多值IN列表

    将逗号分隔数据转换为多值IN列表 2010-03-15 11:16:59|  分类: 数据库技术|举报|字号 订阅     下载LOFTER我的照片书  |     原文:http://book.cs ...

  7. 修改Apache访问权限

    You don't have permission to access / on this server.错误,居然说我此台服务器上无权限,ok解决办法如下: 找到:apache文件,进入conf文件 ...

  8. ChemDraw中化学信息怎么通过Excel搜索

    用户可以通过ChemDraw for Excel插件功能在Office Excel中建立ChemOffice菜单将ChemOffice和Excel结合使用,使用电子表格的最大优势之一就是可以清晰查看并 ...

  9. Git------MyEclipse中使用Git

    转载:http://www.mamicode.com/info-detail-928508.html

  10. JBPM4.4_工作流基础_准备jBPM4.4环境

    1. 工作流基础 1.1. 工作流相关概念 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任 ...