問題: 使用java進行編程時,有時會發現在一個類中明明定義的是private類型,結果卻能夠在其他類中被修改。
代碼:
class Employee{private String name;private double salary;private Date hireDay;public Date getHireDay(){return hireDay;}}
Employee harry = new Employee("harry",75000,1987,12,15);Date d = harry.getHireDay();double tenYearsInMilliSeconds = 10 * 365.25 * 24 * 60 * 60 * 1000;d.setTime(d.getTime() - (long)tenYearsInMilliSeconds);System.out.println(harry.getHireDay()); 按理說這裡hireDay定義成了Date,此時列印輸出的harry的僱傭日期應該是1987年,結果卻是“Wed Dec 14 12:00:00 CST 1977”。。 出錯的原因很微妙。d和harry.HireDay引用了同一個對象,對調用更改其方法就可以自動的改變這個僱員對象的私人狀態。如果這裡在main函數中更改引用的salary,就不會出現這個問題,如:
class Employee{private String name;private double salary;private Date hireDay;public double getSalary(){return salary;}}
double test = harry.getSalary();test = 50;System.out.println(test);System.out.println(harry.getSalary());
列印結果: 50.0
75000.0
解決方案: 如果需要返回一個可變對象的引用,應該首先對它進行複製。對象clone是指存放在另一個位置上的對象副本。下面是修改後的代碼:
class Employee{private String name;private double salary;private Date hireDay;public Date getHireDay(){return hireDay.clone();}} 憑經驗可知,如果需要返回一個可變資料域的拷貝,就應該使用clone。 這裡有的同學可能會想到,如果hireDay用final修飾,是不是就解決了這個問題呢。然而事實並非如此,對於可變的類,使用final修飾符可能會對讀者造成混亂。private final Date hireDay;僅僅意味著儲存在hireDay變數中的對象引用在物件建構之後不能被改變,而並不意味著hireDay對象是一個常量。任何方法都可以對hireDay引用的對象調用setTime更改器。 參考:Java核心技術。