Java对象深复制与浅复制实例详解

yizhihongxing

Java对象深复制与浅复制实例详解

在 Java 中,对象的复制分为浅复制和深复制两种方式。本文将详细讲解 Java 中对象复制的概念、浅复制和深复制的实现方式、以及深浅复制的应用场景。

对象复制的概念

在 Java 中,我们可以通过 new 运算符来生成新的对象实例,但是有时候我们需要创建一个新对象,它的属性和原对象一模一样而且它们内存地址不同,这个时候就需要使用对象复制。

对象复制分为两种方式,浅复制和深复制。

浅复制

浅复制是指创建一个新对象,其属性和原对象的属性全部相同,但是引用类型对象的内存地址仍然相同。也就是说,新对象与原对象的引用对象之间共享内存地址,对其中一个对象的引用对象进行修改会影响到另一个对象的引用对象。

以下是一个浅复制的示例代码:

class Person implements Cloneable {
    String name;
    Phone phone;

    public Person(String name, Phone phone) {
        this.name = name;
        this.phone = phone;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public String toString() {
        return "Person{name='" + name + "', phone=" + phone.toString() + "}";
    }
}

class Phone {
    String model;
    String color;

    public Phone(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public String toString() {
        return "Phone{model='" + model + "', color='" + color + "'}";
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Phone phone = new Phone("iPhone", "white");
        Person person1 = new Person("张三", phone);
        Person person2 = (Person) person1.clone();
        System.out.println("person1: " + person1.toString());
        System.out.println("person2: " + person2.toString());
        // 修改 phone 对象
        phone.model = "Samsung";
        phone.color = "black";
        System.out.println("person1 after modification: " + person1.toString());
        System.out.println("person2 after modification: " + person2.toString());
    }
}

输出结果:

person1: Person{name='张三', phone=Phone{model='iPhone', color='white'}}
person2: Person{name='张三', phone=Phone{model='iPhone', color='white'}}
person1 after modification: Person{name='张三', phone=Phone{model='Samsung', color='black'}}
person2 after modification: Person{name='张三', phone=Phone{model='Samsung', color='black'}}

从上述代码执行的结果可以看出,person1 和 person2 的 phone 引用对象是相同的,当修改 phone 对象时,不论是 person1 还是 person2 都会受到影响。

深复制

深复制是指创建一个新对象,其属性和原对象的属性全部相同,包括引用类型对象的内存地址都是不同的。也就是说,新对象中的所有属性都是全新的,与原对象的属性之间不会共享内存地址,对其中一个对象的引用对象进行修改不会影响到另一个对象的引用对象。

以下是一个深复制的示例代码:

class Person implements Cloneable {
    String name;
    Phone phone;

    public Person(String name, Phone phone) {
        this.name = name;
        this.phone = phone;
    }

    public Object clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.phone = (Phone) phone.clone();
        return person;
    }

    public String toString() {
        return "Person{name='" + name + "', phone=" + phone.toString() + "}";
    }
}

class Phone implements Cloneable {
    String model;
    String color;

    public Phone(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public String toString() {
        return "Phone{model='" + model + "', color='" + color + "'}";
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Phone phone = new Phone("iPhone", "white");
        Person person1 = new Person("张三", phone);
        Person person2 = (Person) person1.clone();
        System.out.println("person1: " + person1.toString());
        System.out.println("person2: " + person2.toString());
        // 修改 phone 对象
        phone.model = "Samsung";
        phone.color = "black";
        System.out.println("person1 after modification: " + person1.toString());
        System.out.println("person2 after modification: " + person2.toString());
    }
}

输出结果:

person1: Person{name='张三', phone=Phone{model='iPhone', color='white'}}
person2: Person{name='张三', phone=Phone{model='iPhone', color='white'}}
person1 after modification: Person{name='张三', phone=Phone{model='Samsung', color='black'}}
person2 after modification: Person{name='张三', phone=Phone{model='iPhone', color='white'}}

从上述代码执行的结果可以看出,person1 和 person2 的 phone 引用对象是不同的,当修改 phone 对象时,只有 person1 被影响,而 person2 没有变化。

深浅复制的应用场景

浅复制和深复制的使用场景是不同的。在实际开发中,应该根据场景选择合适的复制方式。

浅复制适用于以下场景:

  • 对象的属性比较简单。
  • 其中一个对象没必要拥有自己的引用对象副本。

深复制适用于以下场景:

  • 对象的属性比较复杂,其中包含了大量的引用类型对象。
  • 这些引用类型对象必须独立存在,不能共享内存地址。
  • 对象被修改后不希望对另一个对象产生影响。

结论

本文主要讲解了 Java 中对象复制的概念、浅复制和深复制的实现方式,以及深浅复制的应用场景。

在实际开发中,应该根据实际需求选择合适的复制方式,避免因为复制的问题而导致程序出错。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java对象深复制与浅复制实例详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • JavaWeb实战之编写单元测试类测试数据库操作

    下面是JavaWeb实战之编写单元测试类测试数据库操作的完整攻略: 什么是单元测试? 单元测试是指针对程序模块(软件设计的最小单元)来进行正确性检验的测试工作,通常是由开发人员编写用于保证代码质量的测试代码。在软件开发中,单元测试是非常重要的一部分,它能够帮助我们及时发现和修复程序中的缺陷,从而降低维护和开发成本。 单元测试的好处 提高代码质量 减少代码的B…

    Java 2023年5月20日
    00
  • MyBatis5中Spring集成MyBatis事物管理

    下面是关于MyBatis5中Spring集成MyBatis事物管理的完整攻略: 1、引入依赖 首先需要在pom.xml文件中引入MyBatis和Spring的依赖,具体如下: <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</…

    Java 2023年5月20日
    00
  • Java C++ 算法leetcode828统计子串中唯一字符乘法原理

    Java C++ 算法leetcode828统计子串中唯一字符乘法原理 题目描述 给定一个字符串,你需要统计其中唯一字符的个数。 具体地,你需要统计所有的出现恰好一次的字符的个数。 示例 输入: “ABCDEF”输出: 6解释: 出现一次的字符有 ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’,因此唯一字符的个数为 6。 输入: “ABCDEFAB…

    Java 2023年5月19日
    00
  • SpringBoot应用启动流程源码解析

    SpringBoot应用启动流程源码解析 SpringBoot是一款基于Spring框架的快速开发脚手架,具有很高的灵活性和可扩展性。在深入学习SpringBoot应用时,我们需要了解SpringBoot的启动流程。本文将进行“SpringBoot应用启动流程源码解析”的详细讲解,包括SpringBoot应用启动的主要流程、常用的启动方式和相关的代码分析。 …

    Java 2023年5月15日
    00
  • java的Hibernate框架报错“StaleObjectStateException”的原因和解决方法

    当使用Java的Hibernate框架时,可能会遇到“StaleObjectStateException”错误。这个错误通常是由于以下原因之一引起的: 数据库中的数据已被修改:如果您的数据已被修改,则可能会出现此错误。在这种情况下,需要检查您的数据以解决此问题。 并发访问:如果多个用户同时访问同一数据,则可能会出现此错误。在这种情况下,需要使用乐观锁或悲观锁…

    Java 2023年5月4日
    00
  • MyBatis映射器mapper快速入门教程

    MyBatis是一款基于Java语言的ORM框架,能够帮助开发者轻松完成SQL语句的映射配置,提高开发效率。在使用MyBatis框架时,最常用的就是映射器mapper,本篇文章就来详细讲解一下MyBatis映射器mapper的快速入门教程,包括如何创建映射器mapper、配置映射关系及映射器的使用。 创建MyBatis映射器mapper 创建MyBatis映…

    Java 2023年5月20日
    00
  • 基于java开发之系统托盘的应用

    关于“基于Java开发之系统托盘的应用”的开发攻略,我将按照以下步骤进行讲解。 步骤一:创建系统托盘 导入相关包及类 Java提供了一些相关的包和类,至少要导入以下这些: import java.awt.*; import java.awt.event.*; import javax.swing.*; 创建系统托盘 接着,在 Java 中创建系统托盘可以采用…

    Java 2023年5月24日
    00
  • java使用EasyExcel导入导出excel

    下面是使用EasyExcel导入导出Excel的完整攻略。 一、EasyExcel简介 EasyExcel是一个基于Java的简单,快速的Excel解析和生成开源库,它屏蔽了复杂的API实现细节,让开发人员更专注于业务实现。 EasyExcel支持读取Excel、CSV文件和写入Excel文件,支持百万级别的数据操作,而且在写入数据时不会出现OOM的情况。 …

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部