Java浅拷贝 深拷贝

在Java中,除了基本数据类型之外,还存在引用类型,在方法参数传递时,对于基本数据类型,实际上是值传递,引用类型则是地址传递,将原对象的引用传递过去,他们实际上还是指向同一个对象,String是一种特殊的引用类型,有些值类型的样子,,使得它也相当于值传递。
而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象时,只对基本数据类型、String进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,再对引用数据类型进行拷贝的时候,创建了一个新的对象,而且复制其内的成员变量,则认为是深拷贝。
所以所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对类的实例对象这种引用数据类型的不同操作而已。

  • 浅拷贝:对基本数据类型进行值拷贝,引用数据类型只是引用地址拷贝,此为浅拷贝


    image.png
  • 深拷贝:对基本数据类型进行值拷贝,引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝


    image.png

下面是一个深拷贝的例子

//Cloneable 接口,可以看到它其实什么方法都不需要实现。对他可以简单的理解只是一个标记,是开发者允许这个对象被拷贝。
public class Person {
    public int age;
    public String name;
    public List<String> hobbyList;
    public List<Book> bookList;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //super.clone()浅拷贝,使得age、name完成了值拷贝
        Person p = (Person) super.clone();
        //hobbyList、bookList为引用类型,需要进行深度拷贝
        //List<String>只需要完成浅拷贝即可
        p.hobbyList = (List<String>) ((ArrayList<String>) hobbyList).clone();
        List<Book> books = new ArrayList<>();
        for (Book book : bookList) {
            books.add((Book) book.clone());
        }
        p.bookList = books;
        return p;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", hobbyList=" + hobbyList +
                ", bookList=" + bookList +
                '}';
    }
}
public class Book {
    public String bookName;
    public float price;

    public Book(String bookName, float price) {
        this.bookName = bookName;
        this.price = price;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //String、float不需要进行深度拷贝
        return super.clone();
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookName='" + bookName + '\'' +
                ", price=" + price +
                '}';
    }
}
public class Test {

    public static void main(String[] args) {
        Person p = new Person();
        p.name = "小红";
        p.age = 10;
        p.hobbyList = new ArrayList<>();
        p.hobbyList.add("旅游");
        p.hobbyList.add("跑步");
        p.bookList = new ArrayList<>();
        p.bookList.add(new Book("追忆似水年华", 80.0f));
        p.bookList.add(new Book("悲惨世界", 66.0f));

        //对Person p进行深度拷贝
        Person pCopy = null;
        try {
            pCopy = (Person) p.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        pCopy.name = "小明";
        pCopy.age = 15;
        pCopy.hobbyList.set(0, "读书");
        pCopy.bookList.set(0, new Book("简爱", 50.0f));

        System.out.println(p.toString());
        System.out.println(pCopy.toString());

    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 深拷贝和浅拷贝的概念,我自己在学习Java的时候也没注意,虽然Java中对象回收工作由GC帮我们做了,但在码代码时...
    DreamFish阅读 6,028评论 0 6
  • 概要 浅拷贝、深拷贝都是从一个对象中new一个新的对象。区别体现在,被new的这个对象,它的变量如果是引用型的话,...
    坏坏小公子阅读 120评论 0 0
  • 如果类不实现Clonable接口就重写Object中的clone方法就会抛出CloneNotSupportedEx...
    wtmxx阅读 474评论 0 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,547评论 1 32
  • 郭相麟 生活 是想象的搞笑 你对它笑 它给你挤眉弄眼 你对它要求 它给你撅嘴 你对它生气 它给你暴躁 你对它微笑 ...
    郭相麟阅读 305评论 0 0

友情链接更多精彩内容