immutable object提供了极具价值的服务。由于他们保证自己的状态从构建之后就一定不再改变。因此他们天生具备多线程安全性。所以我们可以不必对它进行同步控制,这样可能能够提高些性能。但是实现immutable object时你必须实现clone(克隆)功能,而其代价可能不小。

要将一个类变成immutable是要通过多方面的合作才可能造就不变性:

1 将class中的所有数据声明为private。
2 只提供取值函数(getter),不提供设值函数(setter)。
3 声明class为final。
4 从获取器返回references to mutable object之前,先克隆(cloning)那些mutable object。
5 将传递给构造函数的reference to mutable object先clone
6 在构造函数中设定class内含的所有数据。


final class PinNumbers{

    
private String acctowner;

   
private int checkingApptPin;

   
private int savingsAcctPin;

   PinNumbers(String owner,
int cPin,int sPin){

     acctOwner 
= owner;

     checkingAccPin 
= cPin;

     savingsAcctPin 
= sPin;

   }


   
public String accountOwner(){

     
return acctOwner;

   }


  
public int chechingPin(){


   
return chechingAcctPin;

 }


  
public int savingsPin(){

    
return savingsAcctPin;

  }


}


 这个class不需要克隆(clone)任何数据,因为其构造函数所接受的,或其取值函数(getter)所返回的,都只是基本类型和reference to immutable object。基本类型不是对象,String class是恒常不变的,所以也不需要对它进行clone。

package simplyzhao_DataStructure;

public class User {
    
private String userName;
    
private String userID;
    
private int userNode;  
    
    
public User(String userName, String userID, int userNode)
    
{
        
this.userName = userName;
        
this.userID = userID;
        
this.userNode = userNode;
    }

    
    
public void setUserName(String userName)
    
{
        
this.userName = userName;
    }

    
public String getUserName()
    
{
        
return userName;
    }

    
    
public void setUserID(String userID)
    
{
        
this.userID = userID;
    }

    
public String getUserID()
    
{
        
return userID;
    }

    
    
public void setUserNode(int userNode)
    
{
        
this.userNode = userNode;
    }

    
public int getUserNode()
    
{
        
return userNode;
    }

}

 

package simplyzhao_DataStructure;

public final class DiskDriveInfo {
    
private int driveSize;
    
private String volumeLabel;
    
private User driveShare;

    DiskDriveInfo(
int size, String volLabel,User share)
    
{
        driveSize 
= size;
        volumeLabel 
=volLabel;
        driveShare 
= share;
    }


    
public int size()
    
{
        
return driveSize;
    }


    
public String label()
    
{
        
return volumeLabel;
    }


    
public User share()
    
{
        
return driveShare;
    }

}

上述DiskDriveInfo并不是immutable,因为在DiskDriveInfo可能改变user的值,例如:

package simplyzhao_DataStructure;

public class ImmutableTest {
    
public static void main(String[] args)
    
{
        User user 
= new User("zhaoli""04308032"10001);        
        DiskDriveInfo info 
= new DiskDriveInfo(32"mutable", user);        
        System.out.println(info.share().getUserName());
        user.setUserName(
"panlingyan");
        System.out.println(info.share().getUserName());
    }

}

上述代码的输出为:
zhaoli
panlingyan


想要将DiskDriveInfo类实现为immutable, 首先必须为User类实现clone()方法:

package simplyzhao_DataStructure;

public class User implements Cloneable{
    
private String userName;
    
private String userID;
    
private int userNode;  
    
    
public User(String userName, String userID, int userNode)
    
{
        
this.userName = userName;
        
this.userID = userID;
        
this.userNode = userNode;
    }

    
    
public void setUserName(String userName)
    
{
        
this.userName = userName;
    }

    
public String getUserName()
    
{
        
return userName;
    }

    
    
public void setUserID(String userID)
    
{
        
this.userID = userID;
    }

    
public String getUserID()
    
{
        
return userID;
    }

    
    
public void setUserNode(int userNode)
    
{
        
this.userNode = userNode;
    }

    
public int getUserNode()
    
{
        
return userNode;
    }

    
    
public Object clone()
    
{
        
try {
            User copy 
= (User)super.clone();
            
return copy;
        }
 catch (CloneNotSupportedException e) {
            e.printStackTrace();
            
return null;
        }

    }

}

然后将DiskDriveInfo类的定义修改为:

package simplyzhao_DataStructure;

public final class DiskDriveInfo {
    
private int driveSize;
    
private String volumeLabel;
    
private User driveShare;

    DiskDriveInfo(
int size, String volLabel,User share)
    
{
        driveSize 
= size;
        volumeLabel 
=volLabel;
        driveShare 
= (User)share.clone();
    }


    
public int size()
    
{
        
return driveSize;
    }


    
public String label()
    
{
        
return volumeLabel;
    }


    
public User share()
    
{
        
return (User)driveShare.clone();
    }

}

结果上述测试代码的输出将变成:
zhaoli
zhaoli

假如DiskDriveInfo类里面的不是一个user对象 而是一个Vector,里面保存了许多user对象。 难道时调用Vector里面的clone()吗?可惜Vector克隆的不是整个的对象树,而是克隆了一个Vector但是里面的指向的user对象还是以前那个user对象的。这时候我们就需要深层克隆(Deep Cloning)

如:

class ShareVector extends Vector{

   ShareVector(int Size){

      super(size);

    }

  public Object clone(){

     ShareVector v = (ShareVector)super.clone();

    int size = size();

  for(int i=0;i<size;i++){

    User u = (User)(this.get(i));

     v.setElementAt((User)(u.clone()),i);

   }

  return v;

  }

}

 

或者在DiskDriveInfo中提供一个cloneVector(Vector)的方法好了。

private Vector cloneVector(Vector v){

   int size = v.size();

   Vector newVector = new Vector();

    for(int i=0;i<size;i++){

    newVector.add((User)(v.get(i)).clone));

   return newVector;

   }

}

 

总而言之,在实现了一个immutable class(不可变类)时,请遵守下列规则。

1、声明这个class为final。

2。声明所有的数据为private。

3。只提供取值函数(getter),不提供设值函数(setter)。

4、在构造函数中设置所有的instance数据。

5、如果函数返回references to mutable objects,请先克隆那些mutable objects。

6、如果函数接受references to mutable objects,请先克隆那些mutable objects。

7、如果缺省之浅层克隆(shallow clone)不能符合immutable object的正常行为,请实现出深层克隆(deep cloning)。



 

posted on 2008-04-12 18:11  simply-zhao  阅读(611)  评论(0编辑  收藏  举报