JAVA实现深拷贝和浅拷贝

JAVA实现深拷贝和浅拷贝

能拷贝的对象肯定要需要实现cloneable接口

浅拷贝

只拷贝值,内存地址还一样,只能拷贝基础类型,引用对象不能拷贝

public class HashText {

    public static void main(String[] args) throws CloneNotSupportedException {

        Person person = new Person();
        person.setName("123");
        Friend friend = new Friend();
        friend.setName("f1233");
        person.setFriend(friend);

        System.out.println(person.getName());
        System.out.println(person.getFriend().getName());

        Person person1 = (Person) person.clone();
        person1.setName("456");
        // 修改friend的值
        person1.getFriend().setName("f456");

        System.out.println("基本属性可以拷贝, 不受影响");
        System.out.println("person1-"+person1.getName());
        System.out.println("person-"+person.getName());
        System.out.println("类对象不可以拷贝, 原始对象值也变了");
        System.out.println("person1-"+person1.getFriend().getName());
        System.out.println("person-"+person.getFriend().getName());
    }


    static class Person implements Cloneable {
        private String name;

        private Friend friend;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        public Friend getFriend() {
            return friend;
        }

        public void setFriend(Friend friend) {
            this.friend = friend;
        }
    }

    static class Friend {
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

输出结果:

123
f1233
基本属性可以拷贝, 不受影响
person1-456
person-123
类对象不可以拷贝, 原始对象值也变了
person1-f456
person-f456

深拷贝

值和内存地址都复制成了新的方法

方法1:clone方式

package com.shinho.plrs.sentinel.service;

import javax.annotation.PostConstruct;
import java.util.HashSet;
public class HashText {

    public static void main(String[] args) throws CloneNotSupportedException {

        Person person = new Person();
        person.setName("123");
        Friend friend = new Friend();
        friend.setName("f1233");
        person.setFriend(friend);

        System.out.println(person.getName());
        System.out.println(person.getFriend().getName());

        Person person1 = (Person) person.clone();
        person1.setName("456");
        // 修改friend的值
        person1.getFriend().setName("f456");

        System.out.println("基本属性可以拷贝, 不受影响");
        System.out.println("person1-"+person1.getName());
        System.out.println("person-"+person.getName());
        System.out.println("类对象可以拷贝, 不受影响");
        System.out.println("person1-"+person1.getFriend().getName());
        System.out.println("person-"+person.getFriend().getName());


    }


    static class Person implements Cloneable {
        private String name;

        private Friend friend;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person person = (Person) super.clone();
            person.friend = (Friend) friend.clone();
            return person;
        }

        public Friend getFriend() {
            return friend;
        }

        public void setFriend(Friend friend) {
            this.friend = friend;
        }
    }

    static class Friend implements Cloneable{
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        @Override
        public String toString() {
            return "Friend{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

// 输出
123
f1233
基本属性可以拷贝, 不受影响
person1-456
person-123
类对象可以拷贝, 不受影响
person1-f456
person-f1233

方法2:序列化方式

使用场景,针对于包含数组或者复杂对象,不能简单按照方法1方式实现的。

序列化的方式是让每个类都实现Serializable接口,然后通过序列化和反序列化操作达到深克隆的目的

public class HashText {

    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {

        Person person = new Person();
        person.setName("123");
        Friend friend = new Friend();
        friend.setName("f1233");
        person.setFriend(friend);

        System.out.println(person.getName());
        System.out.println(person.getFriend().getName());

        // 输出流输出person对象
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(stream);
        outputStream.writeObject(person);

        // 输入流读入person的数据流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(stream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        Person person1 = (Person) objectInputStream.readObject();

        // 修改person的值和类对象值
        person1.setName("456");
        person1.getFriend().setName("f456");

        System.out.println("person-原始数据:");
        System.out.println(person.getName());
        System.out.println(person.getFriend().getName());
        System.out.println("person-修改后的数据:");
        System.out.println(person1.getName());
        System.out.println(person1.getFriend().getName());
    }


    static class Person implements Serializable {
        private String name;

        private Friend friend;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person person = (Person) super.clone();
            person.friend = (Friend) friend.clone();
            return person;
        }

        public Friend getFriend() {
            return friend;
        }

        public void setFriend(Friend friend) {
            this.friend = friend;
        }
    }

    static class Friend implements Serializable {
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        @Override
        public String toString() {
            return "Friend{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

输出:

123
f1233
person-原始数据:
123
f1233
person-修改后的数据:
456

扩展-Java 创建对象有几种方式

new 关键字

平时使用的最多的创建对象方式

User user=new User();

反射方式

使用 newInstance(),但是得处理两个异常 InstantiationException、IllegalAccessException:

User user=User.class.newInstance();
Object object=(Object)Class.forName("java.lang.Object").newInstance()

clone方法

Object对象中的clone方法来完成这个操作

反序列化操作

调用 ObjectInputStream 类的 readObject() 方法。我们反序列化一个对象,JVM 会给我们创建一个单独的对象。JVM 创建对象并不会调用任何构造函数。一个对象实现了 Serializable 接口,就可以把对象写入到文中,并通过读取文件来创建对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值