zoukankan      html  css  js  c++  java
  • 对象的复制(浅复制与深复制)

        在Java中如果想将一个基本类型变量的值赋给另一个变量,直接使用等号解可以了,原始的版本改变了,副本并不会发生变化,如下:

    int a=10;
    int b=a;
    a=9;
    System.out.println(a); //9
    System.out.println(b); //10

       但是如果想要复制的变量不是基本类型,而是引用类型的话,就会与上面的效果不同:

    package demos;
    /**
     * Created by hu on 2016/3/26.
     */
    public class People {
        private int age;
        private String name;
        public People(int age,String name){
            this.age=age;
            this.name=name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){
            return this.name+" is "+this.age;
        }
        public static void main(String[] args){
            People p1=new People(12,"tom");
            People p2=p1;
            System.out.println(p1);
            System.out.println(p2);
            p1.setAge(25);
            p1.setName("jack");
            System.out.println(p1);
            System.out.println(p2);
        }
    }
    /*output:
    * tom is 12
    * tom is 12
    * jack is 25
    * jack is 25
    * */     

          在上面的代码中,原始对象发生变化,副本对象也发生了变化,这是因为,执行p2=p1这段代码的时候,只是发生了引用变量的复制,而并没有发生对象的复制,两个引用变量指向的还是同一个对象。

    那么,怎样才能达到复制一个对象呢?
      是否记得万类之王Object。它有11个方法,有两个protected的方法,其中一个为clone方法。
    该方法的签名是:

          protected native Object clone() throws CloneNotSupportedException;

    一般步骤是(浅复制):

    1. 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常) 该接口为标记接口(不含任何方法)

    2. 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,(native为本地方法)

    对上面的代码进行改造,如下:

    package demos;
    /**
     * Created by hu on 2016/3/26.
     */
    public class People implements Cloneable{
        private int age;
        private String name;
        public People(int age,String name){
            this.age=age;
            this.name=name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){
            return this.name+" is "+this.age;
        }
        @Override
        public Object clone(){
            People people = null;
            try{
                people = (People)super.clone();
            }catch(CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return people;
        }
        public static void main(String[] args){
            People p1=new People(12,"tom");
            People p2= (People) p1.clone();
            System.out.println(p1);
            System.out.println(p2);
            p1.setAge(25);
            p1.setName("jack");
            System.out.println(p1);
            System.out.println(p2);
        }
    }
    /*output:
    * tom is 12
    * tom is 12
    * jack is 25
    * tom is 12
    * */

     那么我们还可以在People中再添加一个Address类,如下:

    package demos;
    /**
     * Created by hu on 2016/3/26.
     */
    class Address{
        private String address;
        public Address(String address){
            this.address=address;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString(){
            return address;
        }
    }
    public class People implements Cloneable{
        private int age;
        private String name;
        private Address address;
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public People(int age,String name){
            this.age=age;
            this.name=name;
        }
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){
            return this.name+" is "+this.age+", live in "+address;
        }
        @Override
        public Object clone(){
            People people = null;
            try{
                people = (People)super.clone();
            }catch(CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return people;
        }
        public static void main(String[] args){
            Address address=new Address("LuoYang");
            People p1=new People(12,"tom");
            p1.setAddress(address);
            People p2= (People) p1.clone();
            System.out.println(p1);
            System.out.println(p2);
            p1.setAge(25);
            p1.setName("jack");
            address.setAddress("ZhengZhou");
            System.out.println(p1);
            System.out.println(p2);
        }
    }
    /*output:
    * tom is 12, live in LuoYang
    * tom is 12, live in LuoYang
    * jack is 25, live in ZhengZhou
    * tom is 12, live in ZhengZhou
    * */

    上面的代码,原始的版本对象地址发生了变化,但是副本却没有发生变化,那是因为在进行复制时,只复制了address这个变量的引用,并没有复制该变量指向的对象。此时就需要深度复制,深度复制很简单,只需要将Address也实现Cloneable接口即可,修改如下:

    package demos;
    /**
     * Created by hu on 2016/3/26.
     */
    class Address implements Cloneable{
        private String address;
        public Address(String address){
            this.address=address;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString(){
            return address;
        }
        @Override
        public Object clone(){
            Address address = null;
            try{
                address = (Address)super.clone();
            }catch(CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return address;
        }
    }
    public class People implements Cloneable{
        private int age;
        private String name;
        private Address address;
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public People(int age,String name){
            this.age=age;
            this.name=name;
        }
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){
            return this.name+" is "+this.age+", live in "+address;
        }
        @Override
        public Object clone(){
            People people = null;
            try{
                people = (People)super.clone();
            }catch(CloneNotSupportedException e) {
                e.printStackTrace();
            }
            people.setAddress((Address) people.getAddress().clone());
            return people;
        }
        public static void main(String[] args){
            Address address=new Address("LuoYang");
            People p1=new People(12,"tom");
            p1.setAddress(address);
            People p2= (People) p1.clone();
            System.out.println(p1);
            System.out.println(p2);
            p1.setAge(25);
            p1.setName("jack");
            address.setAddress("ZhengZhou");
            System.out.println(p1);
            System.out.println(p2);
        }
    }
    /*output:
    * tom is 12, live in LuoYang
    * tom is 12, live in LuoYang
    * jack is 25, live in ZhengZhou
    * tom is 12, live in LuoYang
    * */
    

      如此,就是深度复制了。

         总结:浅拷贝是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行拷贝,没有对引用指向的对象进行拷贝。而深拷贝是指在拷贝对象时,同时会对引用指向的对象进行拷贝。区别就在于是否对对象中的引用变量所指向的对象进行拷贝。

  • 相关阅读:
    HDU_1709 The Balence (生成函数)
    Ural_1003 Parity(并查集)
    HDU_1171 Big Event in HDU(生成函数)
    Ural_1306. Sequence Median(堆)
    POJ_2823 Sliding Window(单调队列)
    HDU_2065 "红色病毒"问题(指数型生成函数)
    HDU_2082 找单词 (生成函数)
    最长上升子序列问题(LCS)
    HDU_1284 钱币兑换问题(生成函数)
    HDU_2152 Fruit(生成函数)
  • 原文地址:https://www.cnblogs.com/hujingwei/p/5322858.html
Copyright © 2011-2022 走看看