日期:2014-05-20  浏览次数:20611 次

问一个关于不要编写返回引用可变对象访问器方法的问题
源代码:public   class   EmployeeTest   {
public   static   void   main(String[]   args)
{
Employee[]   staff=new   Employee[3];

staff[0]=new   Employee( "carl   cracker ",10000,1987,12,15);
staff[1]=new   Employee( "harry   hacker ",20000,1987,12,16);
staff[2]=new   Employee( "tony   tester ",30000,1987,12,17);

for(Employee   e:staff)
e.raiseSalary(3);

for(Employee   e:staff)
System.out.println( "name= "+e.getName()+ ",salary= "+e.getSalary()+ ",hireDay= "+e.getHireDay()+ ". ");

}

}


import   java.util.*;  
public   class   Employee   {
private   String   name;
private   double   salary;
private   Date   hireDay;
public   Employee(String   n,double   s,int   year,int   month,int   day)
{
name=n;
salary=s;
GregorianCalendar   calendar=new   GregorianCalendar(year,month-1,day);
hireDay=calendar.getTime();
}

public   String   getName()
{
return   name;
}

public   double   getSalary()
{
return   salary;
}

public   Date   getHireDay()
{
return   hireDay;
}

public   void   raiseSalary(double   percent)
{
double   raise=salary*percent/100;
salary+=raise;
}



}


书上说不要编写返回引用可变对象的访问器方法。其中的getHireDay方法就违反了这个原则。应该改成:
public   Date   getHireDay()
{
return   (Date)hireDay.clone();
}

那其中的方法getName不是返回了一个String类型的数据吗。是不是也应该改写getName方法。改写成:
public   String   getName()
{
return   (String)name.clone();
}


是不是所有返回类对象的方法都要克隆,什么是引用可变的对象?

------解决方案--------------------
String类是不可变的,返回的name如果你再次为它赋值,也不会改变原对象属性。
name= "abc ",将会使返回的这个引用指向一个新的对象 "abc ",这时再调用getName()得到的还是原来的值,不是 "abc "

不要编写返回引用可变对象的访问器方法
这是对的,不可变对象,比如Date类的对象的引用Date date=new Date();如果date是对象的属性,那么你在getHireDay()方法中返回了return date;那么我可以Date d=x.getHireDay();然后d.setHours(5);因为这个d和属性变量date引用的是同一个对象,那么那个private就白加了,我没有通过setHireDay()方法就改了它的值。

所以当需要返回可变对象的引用时要clone(),这是一个新对象,随便改,如果想改属性,那就调set方法。

但是String和java.lang包中的Integer,Byte等包装类都是不可变的,可以放心返回。