首页 > 其他分享 >对象克隆

对象克隆

时间:2023-03-27 13:37:00浏览次数:27  
标签:p2 p1 克隆 对象 age Person partner name

直接赋值

public class ObjectClone {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 25);
        Person p2 = p1;

        // 修改p2会影响到p1
        p2.age = 30;
        p2.name = "李四";
        System.out.println(p1);
    }
}

@Data
@AllArgsConstructor
class Person {
    String name;
    int age;
}

// 输出:Person(name=李四, age=30)

实现Cloneable接口

  1. 实现Cloneable接口
  2. 重写Object类的clone()方法
public class ObjectClone {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 25);
        Person p2 = p1.clone();

        // 修改p2不会影响到p1
        p2.age = 30;
        p2.name = "李四";
        System.out.println(p1);
        System.out.println(p2);
    }
}

@Data
@AllArgsConstructor
class Person implements Cloneable {
    String name;
    int age;

    @Override
    protected Person clone() {
        Person person = null;
        try {
            person = (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return person;
    }
}

// 输出:
Person(name=张三, age=25)
Person(name=李四, age=30)

带引用类型的克隆

给Person类增加引用类型,然后拷贝并修改这个引用类型的值

public class ObjectClone {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 25);
        p1.setPartner(new Person("小红", 22));
        Person p2 = p1.clone();

        // 修改p2的partner会影响到p1
        p2.age = 30;
        p2.name = "李四";
        p2.getPartner().setName("Mary");
        p2.getPartner().setAge(18);
        System.out.println(p1);
        System.out.println(p2);
    }
}

@Data
class Person implements Cloneable {
    String name;
    int age;
    Person partner;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Person clone() {
        Person person = null;
        try {
            person = (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return person;
    }
}

// 输出,发现两个partner变成一样的了
Person(name=张三, age=25, partner=Person(name=Mary, age=18, partner=null))
Person(name=李四, age=30, partner=Person(name=Mary, age=18, partner=null))

// 如果需要对引用类型也单独复制一份,需要再次调用clone()方法
@Override
protected Person clone() {
    Person person = null;
    try {
        person = (Person) super.clone();
        if (partner != null) {
            person.partner = partner.clone();
        }
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    return person;
}

// 输出:
Person(name=张三, age=25, partner=Person(name=小红, age=22, partner=null))
Person(name=李四, age=30, partner=Person(name=Mary, age=18, partner=null))

使用工具类

cn.hutool.core.util.clone(T obj)
克隆对象
如果对象实现Cloneable接口,调用其clone方法
如果实现Serializable接口,执行深度克隆
否则返回null

实现Cloneable,需要自己实现clone()方法,项目维护时,如果增加了引用字段,也很容易忘记去修改clone()方法,所以实现Serializable接口,执行深度克隆的方法比较好

public class ObjectClone {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 25);
        p1.setPartner(new Person("小红", 22));
        Person p2 = ObjectUtil.clone(p1);

        // 修改p2的partner不会影响到p1
        p2.age = 30;
        p2.name = "李四";
        p2.getPartner().setName("Mary");
        p2.getPartner().setAge(18);
        System.out.println(p1);
        System.out.println(p2);
    }
}

@Data
class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    String name;
    int age;
    Person partner;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
// 结果
Person(name=张三, age=25, partner=Person(name=小红, age=22, partner=null))
Person(name=李四, age=30, partner=Person(name=Mary, age=18, partner=null))

标签:p2,p1,克隆,对象,age,Person,partner,name
From: https://www.cnblogs.com/dylmys/p/17258895.html

相关文章

  • 一个关于样式管理器的 Styled 对象!~~
    constStyled=function(dom,styled,datas,isOnlyXid){this.xid=isOnlyXid||getXid();this.dom=dom;this.dom.classList.add(t......
  • .Net 6.0定义全局当前身份缓存对象
    背景:当前身份缓存对象顾名思义就是:当前登录的用户身份对象,那它解决了什么问题呢?其实在我们日常开发过程中经常能用的到几乎是必备的,就比如我给某个表插入数据时......
  • Redis - 对象结构
    简介Redis使用对象存储数据库中的键和值,每当在Redis中创建一个新的键值对时,都会创建两个对象:一个是键对象,另一个是值对象。其中,Redis的每种对象都由对象结构和对应......
  • C#对象与字节数组互相转换
    publicstaticbyte[]ObjectToByteArray(Objectobj){BinaryFormatterbf=newBinaryFormatter();using(varms=newMemoryS......
  • 最全介绍Document对象内容集合
    document文挡对象-JavaScript脚本语言描述———————————————————————注:页面上元素name属性和JavaScript引用的名称必须一致包括大小写......
  • 4、类和对象
    4、类和对象 C++面向对象的三大特性为:封装、继承、多态。C++认为万事万物都皆为对象,对象上有其属性和行为。 例如:人可以作为对象,属性有姓名、年龄、身高、体重.........
  • 面向对象基础
    面向对象概念      面向对象是一种方法论对象和实例     对象  object          定义一个类就会得到一个类对象Object ......
  • 动态创建对象执行方法
    packageedu.wtbu;importjava.lang.reflect.Constructor;importjava.lang.reflect.Field;importjava.lang.reflect.InvocationTargetException;importjava.lang.refle......
  • java----对象的的创建和使用
    对象的的创建和使用创建一个学生类publicclassStudent{/*创建一个学生类*///下面是成员变量Stringname;//intage;intweight;//下......
  • 浏览器对象属性 window.innerWidth 和 window.outerWidth 这两个宽度属性有何区别?
    window.innerWidth和window.outerWidth是两个浏览器对象属性,分别代表浏览器窗口的内部宽度和外部宽度。它们的区别如下:window.innerWidth:表示浏览器窗口的内部宽度......