1. //不可变类  
  2. package bin;  
  3.  
  4. class Name  
  5. {  
  6.     private String firstName;  
  7.     private String lastName;  
  8.     public Name(){}  
  9.     public Name(String firstName,String lastName)  
  10.     {  
  11.         this.firstName = firstName;  
  12.         this.lastName = lastName;     
  13.     }     
  14.     public void setFirstName(String firstName)  
  15.     {  
  16.         this.firstName = firstName;   
  17.     }  
  18.     public String getFirstName()  
  19.     {  
  20.         return firstName;     
  21.     }  
  22.     public void setLastName(String lastName)  
  23.     {  
  24.         this.lastName = lastName;     
  25.     }  
  26.     public String getLastName()  
  27.     {  
  28.         return lastName;      
  29.     }  
  30. }  
  31. //定义Person不可变类  
  32. public class Person  
  33. {  
  34.     private final Name name;  
  35.     /*  
  36.     原来的代码  
  37.     public Person(Name name)  
  38.     {  
  39.         this.name = name;  
  40.     }     
  41.     public Name getName()  
  42.     {  
  43.         return name;  
  44.     }  
  45.     */ 
  46.     //改进的代码  
  47.     public Person(Name name)  
  48.     {  
  49.         this.name = new Name(name.getFirstName(),name.getLastName());//*  
  50.     }     
  51.     public Name getName()  
  52.     {  
  53.         return new Name(name.getFirstName(),name.getLastName());    //*  
  54.     }  
  55.     public static void main(String[] args)  
  56.     {  
  57.         Name n = new Name("悟空","孙");  
  58.         Person p = new Person(n);  
  59.         System.out.println(p.getName().getFirstName());  
  60.         n.setFirstName("八戒");     
  61.         System.out.println(p.getName().getFirstName());  
  62.     }  
  63.     /*  
  64.         原来是程序中Person对象的Name属性的firstName属性改变,就导致Person的改变  
  65.         原来输出结果为:悟空,八戒。破坏了Person类的设计初衷。  
  66.         为了保持Person对象的不可变,必须保护好Person对象的引用类型属性:name,让程序  
  67.         无法访问到Person对象的name属性,也就无法利用name属性的可变性来改变Person对象了  
  68.           
  69.         更改后:当程序向Person构造器里传入一个Name对象时,该构造器创建Person对象时并不是  
  70.         直接利用已有的Name对象(利用已有的Name对象有风险,因为这个Name对象的可变的,如果  
  71.         改变这个Name对象,Person也将改变),而是重新创建了一个Name对象来赋给Person对象的  
  72.         name属性。当Person对象返回name属性时,不没有直接把name属性返回,直接返回name属性  
  73.         也可能导致该name属性所引用的Name对象被修改。  
  74.         修改后结果:悟空 悟空  
  75.     */