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

createh55个月前 (02-01)技术教程31

【死记硬背】

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

直接赋值拷贝:这个实际上复制的是对象的引用地址,如: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%免费领取楼主的所有面试题资料!

相关文章

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

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

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

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

④ JAVA IO—拷贝(java拷贝文件夹到另外一个文件夹)

一、 传统的IO1. 数据由磁盘拷贝到内核空间(DMA),再由内核空间拷贝到用户空间(JVM)2. 用户可能会对拷贝进来的数据进行操作3. 数据从用户空间拷贝到内核空间(JVM),再通过内核空间将数据...

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

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

java浅拷贝BeanUtils.copyProperties引发的RPC异常

背景近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到 人在地铁上,bug从咚咚来~没有任何修改的服务接口,抛出异常:jav...