天天看點

java clone 之深拷貝、淺拷貝

由于指針不僅給開發人員帶來使用上的不變,而且也是造成程式不穩定的根源,為了根除c++語言的這些缺點,java語言取消了指針的概念,但這隻是在java語言中沒有明确提供指針的概念與用法,二實質每個new語句傳回的都是一個指針的引用,隻不過在大部分情況下開發人員不需要關心如何取操作這個指針而已。是以,開發人員在程式設計中往往忽略了對象與引用的差別。

  java在處理基本資料類型(byte,int ,short,long,float,double,char,boolean)時采用按值傳遞,傳遞的是輸入參數的複制,除此之外的其他類型都是采用按引用傳遞,傳遞的對象的引用,實際上指向的是同一個對象。對象除了在函數調用時是引用傳遞,指派時也是采用引用傳遞。

 在實際程式設計中,經常會遇到某個已有的對象A建立出另一個與A具有相同狀态的對象B,并且對B的修改不會影響到A的狀态。例如,prototype原型模式中就需要clone一個對象執行個體。java中僅僅通過簡單的指派操作顯然無法達到這個目的。至此,clone正式登場。

clone()方法的使用步驟:

 1.首先繼承cloneable 接口,一個辨別接口。

 2.在類中重寫object的clone方法

3.在clone方法中調用super.clone();

4.把潛複制的引用指向原型對象新的克隆體。

package com.dh.DpsdkCore.TvWall;

class Obj implements Cloneable {

    private int a = 0;

    public int getA() {

        return a;

    }

    public void setA(int a) {

        this.a = a;

    }

    public void changint() {

        this.a = 1;

    }

    //重寫clone方法

    public Object clone() {

        Object o = null;

        try {

            o = super.clone();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return o;

    }

}

public class TestClone() {

    //jvm的入口

    public static void main (String[] args){

        Obj a=new Obj();

        Obj b=(Obj)a.clone();

        b.changint();

        System.out.println("a:"+a.getA());//0

        System.out.println("b:"+b.getA());//1

    }

    }

b的變化并沒有影響到a.。

在c語言中,當開發人員自定義複制構造函數時,會存在潛複制和深複制之分。java在重載clone()時畢業存在同樣的問題。當類中隻有一些基本資料類型時,采用上述方法就可以了,但是當類中包含一些對象時,就需要用到深複制了。實作方法就是在對對象調用clone()完成複制後,接着則對對象中的非基本資料類型的屬性也調用clone()來完成深複制。

package com.dh.DpsdkCore.TvWall;

import java.util.Date;

class Obj implements Cloneable {

    private int a = 0;

    private Date birth=new Date();

    public int getA() {

        return a;

    }

    public void setA(int a) {

        this.a = a;

    }

    public void changint() {

        this.a = 1;

    }

    public Date getBirth() {

        return birth;

    }

    public void setBirth(Date birth) {

        this.birth = birth;

    }

    //重寫clone方法

    public Object clone() {

        Object o = null;

        try {

            o = super.clone();

        } catch (Exception e) {

            e.printStackTrace();

        }

         //實作深複制

        o.birth=(Date)this.getBirth().clone();

        return o;

    }

}

public class TestClone() {

    //jvm的入口

    public static void main (String[] args){

        Obj a=new Obj();

        Obj b=(Obj)a.clone();

        b.changint();

        System.out.println("a:"+a.getA());//0

        System.out.println("b:"+b.getA());//1

    }

    }

clone的保護機制:

在Object中Clone()是被申明為protected的,這樣做是有一定的道理的。在Object中clone()是被聲明為protected的,利用protected修飾clone()方法,是為了安全考慮。Object類中的clone方法是淺拷貝,如果是對象,它拷貝的隻是這個對象的一個引用,而這個引用仍然指向那個對象,當我們改變這個引用的屬性時,原來對象也會跟着改變,這不是我們希望看到的,但是Object類肯定做不到深拷貝,因為它不知道你的類裡有哪些引用類型,是以把修飾符定義為protected,這樣想要在其他任何地方調用這個類的clone方法,這個類就必須去重寫clone方法并且把修飾符改為public,這樣在任何地方都可以調用這個類的clone方法了。