1. 程式人生 > >JAVA如何實現深拷貝

JAVA如何實現深拷貝

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方法只是將各個域進行拷貝。數值或基本型別不會出現問題,但是,如果在物件中包含了引用物件,這些物件的內容沒有被自我複製,拷貝的結果也即是原始物件和拷貝物件引用著同一個引用物件(一般地,動詞“引用”可理解為“管理”,就是指向同一記憶體)。

淺拷貝滿足:

  1. x.clone() != x為 true
  2. x.clone().getClass() == x.getClass()true
  3. ((x.clone().field1 ) == (x. field1))&& … &&((x.clone().fieldN )==(x. fieldN))也為 true 。

如果原始物件與淺拷貝物件共同引用(管理、指向)的引用物件是不可變的,將不會產生任何問題,如,引用物件是String類物件;或引用物件在其生命週期不會發生變化,具體來說,管理它的類中沒有更改它的方法,也沒有返回對它引用的方法(分享其管理權的方法)。

如果原始物件管理的引用物件是可變的,就必須需重新定義clone方法,來實現深層次的拷貝。要對涉及的每一個類,判斷以下兩點:

  • 預設的clone方法是否滿足需求。
  • 預設的clone方法是否能通過呼叫可變引用物件的clone方法得到解決。

對涉及的每一個類,深拷貝要滿足:

  1. x.clone() != x為 true
  2. x.clone().getClass() == x.getClass()true
  3. x.clone().equals(x)也為 true ,當然equals方法是如此重寫過的

Object類中的clone方法被宣告為protected,防止出現文章開頭所提到的,子類和超類不在同一個包下的情況,要宣告clonepublic,來實現深拷貝:


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