java面试基础 -- 深克隆 & 浅克隆

简介: java面试基础 -- 深克隆 & 浅克隆


引例

       说到java的克隆你还记得多少? 一说到克隆你可能就会想起来那个接口, 没错, 他就是Cloneable

       Cloneable是java里面内置的很常用的接口, 我们说 Object类中也有一个clone方法:

        但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.

        于是, 我们创建一个类为Dog类, 如下:

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Dog dog1 = new Dog();
        Dog dog2 = (Dog) dog1.clone();
        System.out.println(dog1 == dog2);
    }
}
 
class Dog implements Cloneable {
    public String dogName;
 
    public int dogAge;
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Dog newDog = null;
        newDog = (Dog) super.clone();
        return newDog;
    }
}

输出结果:




深克隆 vs 浅克隆

       浅克隆只复制对象本身和对象的本数据类型字段,而不复制引用类型字段所指向的对象.

这里的引用类型, 可以是类的引用, 也可以是字符串等.

       我们说实现了Cloneable接口的类拷贝出来的对象是浅拷贝还是深拷贝???

案例:

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal animal1 = new Animal();
        Animal animal2 = (Animal) animal1.clone();
        animal2.classIn = 2;
        animal2.dog.name = "小白";
        System.out.println(animal1.toString());
        System.out.println(animal2.toString());
    }
}
 
class Dog {
    String name = "小黑";
}
class Animal implements Cloneable {
    public Dog dog = new Dog();
 
    public int classIn = 1;
 
    @Override
    public String toString() {
        return "Animal{" +
                "dogName=" + dog.name +
                ", classIn=" + classIn +
                '}';
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

输出结果:

       可以看出来, 他们里面的类的实例却是共享的, 里面的类的引用不同, 但是引用的是同一个类对象. 这就是浅拷贝.




如何深克隆

深克隆基本数据类型变量和引用类型变量指向的对象都会被复制,即针对引用类型的成员变量真正的复制一份,重新开辟空间保存,这样两个引用类型属性互不影响。

       那么如何进行深拷贝呢??

        很容易想到的一点就是, 在重写object中的clone方法, 然后对被克隆的类里面的类引用继续克隆. 也就是嵌套克隆

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal animal1 = new Animal();
        Animal animal2 = (Animal) animal1.clone();
        animal2.classIn = 2;
        animal2.dog.name = "小白";
        System.out.println(animal1.toString());
        System.out.println(animal2.toString());
    }
}
 
class Dog implements Cloneable{
    String name = "小黑";
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Animal implements Cloneable {
    public Dog dog = new Dog();
 
    public int classIn = 1;
 
    @Override
    public String toString() {
        return "Animal{" +
                "dogName=" + dog.name +
                ", classIn=" + classIn +
                '}';
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Animal newAnimal = (Animal) super.clone();
        newAnimal.dog = (Dog) dog.clone();
        return  newAnimal;
    }
}

输出结果:

目录
相关文章
|
9天前
|
XML 前端开发 Java
java面试题之个人对SpringMvc的原理实现理解
java面试题之个人对SpringMvc的原理实现理解
|
9天前
|
缓存 Java 调度
java面试题之个人对线程池的理解
java面试题之个人对线程池的理解
|
9天前
|
缓存 运维 负载均衡
java面试题之个人对正向代理和反向代理的理解
java面试题之个人对正向代理和反向代理的理解
|
3天前
|
存储 安全 算法
Java基础19-一文搞懂Java集合类框架,以及常见面试题(二)
Java基础19-一文搞懂Java集合类框架,以及常见面试题(二)
32 8
|
3天前
|
安全 Java 开发工具
Java基础19-一文搞懂Java集合类框架,以及常见面试题(一)
Java基础19-一文搞懂Java集合类框架,以及常见面试题(一)
31 6
|
3天前
|
安全 Java 程序员
Java基础18-一文搞懂Java多线程使用方式、实现原理以及常见面试题(二)
Java基础18-一文搞懂Java多线程使用方式、实现原理以及常见面试题(二)
23 4
|
3天前
|
Java 程序员 调度
Java基础18-一文搞懂Java多线程使用方式、实现原理以及常见面试题(一)
Java基础18-一文搞懂Java多线程使用方式、实现原理以及常见面试题(一)
22 0
Java基础18-一文搞懂Java多线程使用方式、实现原理以及常见面试题(一)
|
3天前
|
存储 缓存 Java
Java基础17-读懂Java IO流和常见面试题(二)
Java基础17-读懂Java IO流和常见面试题(二)
15 0
|
3天前
|
存储 Java Unix
Java基础17-读懂Java IO流和常见面试题(一)
Java基础16-读懂Java IO流和常见面试题(一)
17 0
|
3天前
|
Java
Java基础7-一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别(二)
Java基础7-一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别(二)
9 0