如果需要设计一个不可变类,尤其要注意其引用类型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. Libgdx多线程与渲染线程

    http://www.leestorm.com/post/115.html ——————————————————————————————————————————————————————————‘ 大部 ...

  2. KMP + 求相等前后缀--- POJ Seek the Name, Seek the Fame

    Seek the Name, Seek the Fame Problem's Link: http://poj.org/problem?id=2752 Mean: 给你一个字符串,求这个字符串中有多少 ...

  3. heartbeat 心跳技术

    转自:http://blog.csdn.net/keda8997110/article/details/8349049 heartbeat 心跳技术原理: heartbeat (Linux-HA)的工 ...

  4. android 开发之hello world!

    http://blog.sina.com.cn/s/blog_4e08922b0100nh6e.html http://blog.csdn.net/poechant/article/details/7 ...

  5. 单引號转义符q’的使用

    当字符串包括单引號时,能够使用转义符q'对单引號进行转义. q'后面的字符能够是:     !     [ ]     { }     ( )     < > 前提是这些字符不会出如今兴许 ...

  6. hdu 1426:Sudoku Killer(DFS深搜,进阶题目,求数独的解)

    Sudoku Killer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  7. 【python】NLTK好文

    From:http://m.blog.csdn.net/blog/huyoo/12188573 nltk是一个python工具包, 用来处理和自然语言处理相关的东西. 包括分词(tokenize), ...

  8. python+selenium之简单介绍继承

    python+selenium之简单介绍继承 一.此例简单的介绍一下继承 1.面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制.继承完全可以理解成类之间的类型和子类型 ...

  9. 'not all arguments converted during string formatting'错误告警信息解决办法

    问题描述:

  10. ajax的轮询和长轮询

    概念: 轮询(polling):客户端按规定时间定时像服务端发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 概念总是枯燥的,只有代码方能解心头之快 前段代码:index.html: & ...