你知道Java的对象拷贝方式有哪几种吗?

createh54个月前 (02-01)技术教程24

【死记硬背】

总共有四种,分别是直接赋值拷贝、浅拷贝、深拷贝和序列化。

直接赋值拷贝:这个实际上复制的是对象的引用地址,如:Person p1 = p2,则p1和p2指向的是同一个对象的地址。因此,p1属性变化的时候,p2的属性也会跟着变化。

浅拷贝:复制引用但不复制引用的对象,如果对象的字段是值类型的,那么对该字段执行复制,如果该字段是引用类型的话,则复制引用但不复制引用的对象。

深拷贝:不仅复制对象本身,而且复制对象包含的引用指向的所有对象。

序列化:对象实现Serializable接口,然后将对象写到流中,再从流中读出来,再重建对象。

【答案解析】

直接赋值拷贝

public class Person{
    private String name;
    private int age;
    private Address address;
    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 Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}
public class Address{
    private String home;
    public String getHome() {
        return home;
    }
    public void setHome(String home) {
        this.home = home;
    }
    @Override
    public String toString() {
        return "Address{" +
                "home='" + home + '\'' +
                '}';
    }
}
public class Test{
    public static void main(String[] args) {
        Address address = new Address();
        address.setHome("浙江省杭州市");
        Person person = new Person();
        person.setName("面试题解析");
        person.setAge(20);
        person.setAddress(address);
        Person person2 = person;
        System.out.println("person年龄变化前:"+person2);
        person.setAge(22);
        System.out.println("person年龄变化后:"+person2);
    }
}
// 输出如下
person年龄变化前:Person{name='面试题解析', age=20, address=Address{home='浙江省杭州市'}}
person年龄变化后:Person{name='面试题解析', age=22, address=Address{home='浙江省杭州市'}}

浅拷贝

public class Person implements Cloneable{
    private String name;
    private int age;
    private Address address;
    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 Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
        try{
            Object o = super.clone();
            Person p = (Person)o;
            return p;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

深拷贝

public class Person implements Cloneable{
    private String name;
    private int age;
    private Address address;
    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 Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
        try{
            Object o = super.clone();
            Person p = (Person)o;
            Object address = this.address.clone();
            p.setAddress((Address) address);
            return p;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

序列化

特点必须实现Serialable接口,使用ObjectInputStream和ObjectOutputStream两个类来实现复制拷贝功能(序列化和反序列化)。

【温馨提示】

点赞+收藏文章,关注我并私信回复【面试题解析】,即可100%免费领取楼主的所有面试题资料!

相关文章

你还在用BeanUtils进行对象属性拷贝?

在做业务的时候,为了隔离变化,我们会将DAO查询出来的DO和对前端提供的DTO隔离开来。大概90%的时候,它们的结构都是类似的;但是我们很不喜欢写很多冗长的b.setF1(a.getF1())这样的代...

java对象深拷贝的三种实现方式,可避免循环引用导致的堆栈溢出

在java编程中,难免要对一个对象进行复制,复制分为深拷贝和浅拷贝。浅拷贝只复制对象本身,对于对象引用的其他对象不进行复制。 深拷贝则将对象与引用对象,全部进行拷贝。最简单的深拷贝就是自己new一个对...

Java中的深拷贝和浅拷贝的原理以及区别

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是在Java编程中与对象复制有关的两个概念,表面上看二者都可以实现对象的复制,但是在复制的方式以及实现效果上却有着很大的区别,下面我们就...

Java中深拷贝、浅拷贝、赋值的区别?如何自己写个深拷贝工具类?

#头条创作挑战赛#为什么要了解JavaBean深拷贝的机制目前大家都在常用已经封装好的工具类,很少去深入了解多种实现方式;此处提出一种简单的实现原理,也是巩固Java中关于反射的用法和知识;目的:可以...

日拱一卒:Java 如何实现对象的 clone?

大家好,我是菜菜,一个为 coding 而生,为 debug 奋斗一辈子的地地道道的码农。日拱一卒系列,旨在通过对 Java 后端常见的面试题进行剖析,少走弯路,利用有限的精力,更加高效的准备和学习。...

Java 简单易用的深拷贝开源库(java深拷贝工具)

浅拷贝是指在对一个对象进行拷贝时,只拷贝对象本身和其中的基本数据类型,而不拷贝对象内部的引用类型。因此,在浅拷贝的对象中,引用类型的变量指向的依旧是原始对象中的引用。深拷贝是指在对一个对象进行拷贝时,...