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

createh52个月前 (02-01)技术教程17

【死记硬背】

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

直接赋值拷贝:这个实际上复制的是对象的引用地址,如: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的深拷贝与浅拷贝详解图)

前言拷贝,顾名思义,就是复制一个一模一样的东西。那么放到对象上,也就是复制一个一模一样的对象了。Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返...

Java常用的几种属性拷贝工具类使用总结

Java属性拷贝工具类使用总结对项目中经常使用的属性拷贝工具类进行总结:org.apache.commons.beanutils.BeanUtilsorg.apache.commons.beanuti...

克隆Java(克隆java项目后爆红)

一. 泛型克隆接口:o JDK自带的Cloneable接口虽然表明一个类支持克隆,但并未提供实际的方法实现。o 文档提出了一种泛型化的Cloneable接口变体,该接口要求实现类提供一个类型安全的cl...

今天搞懂Linux零拷贝(linux操作系统拷贝命令)

Linux零拷贝很多人都听过零拷贝zero-copy的大名,知道在很多牛掰的中间件(比如rocketmq)中为了提高效率,都是用了这项技术。但是,zero-copy到底是怎么回事?今天我想把他彻底搞明...