JAVA如何實現深拷貝
阿新 • • 發佈:2019-02-06
protected 域(或方法)微妙的規則
protected
域(或方法)對本包內的所有類可見(當然包括子類),那麼,子類可以獲得訪超類受保護域(或方法)的權利,但是,若子類和超類不在同一個包下,就不能訪問超類物件的這個受保護域(或方法)。也就是說,不在一個包下,子類中不能通過一個父類物件的引用來獲得父類受保護的域(或方法),測試如下。
package protect2;
public class P{
protected int a;
public P(){}
public P(int a){
this.a = a;
}
protected void fun(){
System.out.println("父類protected方法");
}
}
package protect2;
public class ProtectedTest {
public String s;
public ProtectedTest(String s) {
this.s = s;
}
P ap = new P(10);
void foo() {
ap.fun();
System.out.println("ap.a " + ap.a);
}
public static void main(String[] args) {
ProtectedTest test = new ProtectedTest("abcdef");
test.foo();
System.out.println(test.s);
}
}
package protect;
import protect2.P;
class C extends P{
public int b;
public C(int a,int b){
super(a);
this.b = b;
}
public void afun(){
P pp = new P(10);
System.out.println("C.a= " + a);
System.out.println("P.a= " + pp.a);//ERROR:The field P.a is not visible
pp.fun(); //ERROR:The method fun() from the type P is not visible
}
淺拷貝與深拷貝
Object類對自己的具體子類的域一無所知,Object
類的clone
方法只是將各個域進行拷貝。數值或基本型別不會出現問題,但是,如果在物件中包含了引用物件,這些物件的內容沒有被自我複製,拷貝的結果也即是原始物件和拷貝物件引用著同一個引用物件(一般地,動詞“引用”可理解為“管理”,就是指向同一記憶體)。
淺拷貝滿足:
x.clone() != x
為true
,x.clone().getClass() == x.getClass()
為true
,((x.clone().field1 ) == (x. field1))&& … &&((x.clone().fieldN )==(x. fieldN))
也為true
。
如果原始物件與淺拷貝物件共同引用(管理、指向)的引用物件是不可變的,將不會產生任何問題,如,引用物件是String類物件;或引用物件在其生命週期不會發生變化,具體來說,管理它的類中沒有更改它的方法,也沒有返回對它引用的方法(分享其管理權的方法)。
如果原始物件管理的引用物件是可變的,就必須需重新定義clone
方法,來實現深層次的拷貝。要對涉及的每一個類,判斷以下兩點:
- 預設的clone方法是否滿足需求。
- 預設的clone方法是否能通過呼叫可變引用物件的clone方法得到解決。
對涉及的每一個類,深拷貝要滿足:
x.clone() != x
為true
,x.clone().getClass() == x.getClass()
為true
,x.clone().equals(x)
也為true
,當然equals方法是如此重寫過的。
Object
類中的clone
方法被宣告為protected
,防止出現文章開頭所提到的,子類和超類不在同一個包下的情況,要宣告clone
為public
,來實現深拷貝:
import java.util.Date;
public class EqualsT {
public static void main(String[] args) throws CloneNotSupportedException {
Date hireDay = new Date();
Employee e1 = new Employee("Tommy", 10, "9998", hireDay);
Employee e2 = new Employee("Tommy", 10, "9998", hireDay);
System.out.println(e1.equals(e2));
System.out.println(e1 == e2);
Employee e3 = (Employee) e1.clone();
System.out.println(e1.equals(e3));
}
}
//Cloneable為標記介面,介面內沒有方法。
class Employee implements Cloneable {
String name;
int age;
String salary;
Date hireDay;
public Employee(String name, int age, String salary, Date hireDay) {
super();
this.name = name;
this.age = age;
this.salary = salary;
this.hireDay = hireDay;
}
@Override
public boolean equals(Object otherObject) {
if (this == otherObject)
return true;
if (otherObject == null)
return false;
if (!(otherObject instanceof Employee))
return false;
Employee other = (Employee) otherObject;
return name.equals(other.name) && age == other.age && salary.equals(other.salary)
&& hireDay.equals(other.hireDay);
}
@Override
protected Object clone() throws CloneNotSupportedException {
// call Object.clone()
Employee cloned = (Employee) super.clone();
// call mutable fields
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
}
Output:
true
false
true
// JDK中Date類的克隆方法
public Object clone() {
Date d = null;
try {
d = (Date)super.clone();
if (cdate != null) {
d.cdate = (BaseCalendar.Date) cdate.clone();
}
} catch (CloneNotSupportedException e) {} // Won't happen
return d;
}
以下程式碼與本文無關,請自行跳過
<P><A href="http://xzmobile.zztj120.com/"><FONT color=#ffffff>鄭州同濟婦科醫院</FONT>
<P><A href="http://wapyyk.39.net/zz3/zonghe/1d426.html"><FONT color=#ffffff>鄭州婦科醫院</FONT>
<P><A href="http://wapyyk.39.net/zz3/zonghe/1d426.html"><FONT color=#ffffff>鄭州婦科醫院</FONT>
<P><A href="http://www.lnljyy.com/"><FONT color=#ffffff>鄭州做人流價格是多少錢</FONT>
<P><A href="http://yiyuan.120ask.com/zzfck/"><FONT color=#ffffff>鄭州婦科醫院哪家好</FONT></A></P>
——@guoyangde http://www.cnblogs.com/LittleTreasureBox/p/8904016.html