java 克隆

  有些时候,我们需要对创建一个和已有对象A完全相同的新对象B,但是这个B不是A的引用,即A和B是两个完全独立的对象,虽然他们的属性相同,修改A的任何属性都不会对B产生影响,这个时候就要用到clone啦

clone有两种:

1深克隆:对克隆对象中所有的引用属性对象都进行克隆。

2浅克隆:仅克隆对象的基本类型数据和引用,即只克隆引用对象的地址,而不是克隆被引用的对象。(String类型除外,它表面上和基本类型一样实现了深克隆)

下面通过举例说明

1、深克隆

public class Test {
    public static void main(String[] args)
    {
        Stu stu1=new Stu();
        stu1.setAge(5);
        stu1.setName("Zhang");
        
        Stu stu2=(Stu)stu1.clone();
        stu2.setName("Cheng");
        
        System.out.println(stu1.getAge());
        System.out.println(stu1.getName());
        System.out.println(stu2.getAge());
        System.out.println(stu2.getName());
    }
}
public class Stu implements Cloneable{
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Object clone()
    {
        Stu stu=null;
        try{
            stu=(Stu)super.clone();
        }catch(CloneNotSupportedException ex)
        {
            ex.printStackTrace();
        }
        return stu;
    }
}

输出:

5
Zhang
5
Cheng

  克隆有两点需要注意:1.必须实现Cloneable接口,假如不实现这个接口直接实现clone方法会抛出CloneNotSupport异常

            2、必须实现clone方法,且方法必须是public的,这是因为Object本身就有个方法clone,不过这个方法时protected,另外这个方法时native方法,      效率比非native方法高。

2、浅拷贝

public class Stu implements Cloneable{
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String toString()
    {
        return "age="+age+"   name="+name;
    }
}

public class Test {
    static class League implements Cloneable
    {
        int level;
        Stu stu;
        public int getLevel() {
            return level;
        }
        public void setLevel(int level) {
            this.level = level;
        }
        public Stu getStu() {
            return stu;
        }
        public void setStu(Stu stu) {
            this.stu = stu;
        }
        public String tosString()
        {
            return "level="+level+"    age="+stu.getAge()+"   name="+stu.getName();
        }
        
        public Object clone()
        {
            League league=null;
            try{
                league=(League)super.clone();
            }catch(CloneNotSupportedException ex)
            {
                ex.printStackTrace();
            }
            //league.stu=(Stu)stu.clone();
            return league;
        }
    }
    public static void main(String[] args)
    {
        Stu stu1=new Stu();
        stu1.setAge(5);
        stu1.setName("Zhang");
        
        League league1=new League();
        league1.setLevel(2);
        league1.setStu(stu1);
        League league2=(League)league1.clone();
        league2.getStu().setName("Cheng");
        System.out.println(league1.tosString());
        System.out.println(league2.tosString());
    }
}

输出:

level=2    age=5   name=Cheng
level=2    age=5   name=Cheng

这里进行克隆过后,对克隆对象的修改会影响到被克隆对象,那么怎么才能避免呢

只要在League的对象属性Stu,也实现Clone即可,另外在League的clone方法里面加上league.stu=(Stu)stu.clone();即可

如下

public class Test {
    static class League implements Cloneable
    {
        int level;
        Stu stu;
        public int getLevel() {
            return level;
        }
        public void setLevel(int level) {
            this.level = level;
        }
        public Stu getStu() {
            return stu;
        }
        public void setStu(Stu stu) {
            this.stu = stu;
        }
        public String tosString()
        {
            return "level="+level+"    age="+stu.getAge()+"   name="+stu.getName();
        }
        
        public Object clone()
        {
            League league=null;
            try{
                league=(League)super.clone();
            }catch(CloneNotSupportedException ex)
            {
                ex.printStackTrace();
            }
            league.stu=(Stu)stu.clone();
            return league;
        }
    }
    public static void main(String[] args)
    {
        Stu stu1=new Stu();
        stu1.setAge(5);
        stu1.setName("Zhang");
        
        League league1=new League();
        league1.setLevel(2);
        league1.setStu(stu1);
        League league2=(League)league1.clone();
        league2.getStu().setName("Cheng");
        System.out.println(league1.tosString());
        System.out.println(league2.tosString());
    }
}

public class Stu implements Cloneable{
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String toString()
    {
        return "age="+age+"   name="+name;
    }
    public Object clone()
    {
        Stu stu=null;
        try{
            stu=(Stu)super.clone();
        }catch(CloneNotSupportedException ex)
        {
            ex.printStackTrace();
        }
        return stu;
    }
}

输出
level=2    age=5   name=Zhang
level=2    age=5   name=Cheng

另外不是所有的类都可以实现深度克隆的,包含StringBuilder的类不能被深度克隆,因为该类没有重载clone方法,并且该类是一个final类,无法实现clone。

小弟菜鸟一枚,初来乍到,有什么错误还望各位大神不吝指出,^_^。
原文地址:https://www.cnblogs.com/maydow/p/4461073.html