java 中clone()的使用方法

yizhihongxing

Java 中 clone() 的使用方法

什么是 clone() 方法

clone() 方法是一个 Object 类下的方法,用于返回对象的一个副本。如果一个类要使用 clone() 方法,则这个类必须实现 Cloneable 接口并覆盖 clone() 方法,否则会抛出 CloneNotSupportedException 异常。

如何使用 clone() 方法

实现 Cloneable 接口

实现 Cloneable 接口的类是为了表明这个类是可以进行拷贝的。Cloneable 接口没有方法需要实现,只是强调一个类能否被克隆。如下是一个橘子(Orange)类的示例:

public class Orange implements Cloneable {
    private String name;
    private Double weight;

    public Orange(String name, Double weight) {
        this.name = name;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public Double getWeight() {
        return weight;
    }

    @Override
    public Orange clone() throws CloneNotSupportedException {
        return (Orange) super.clone();
    }
}

如上例中,我们实现了 Cloneable 接口,并重写了 clone() 方法,没有特别的逻辑,直接调用了超类的 clone() 方法。

注意:如果要实现深拷贝,需要在重写的 clone() 方法中进行特定的逻辑实现。

使用 clone() 方法

我们可以通过如下方式来调用 clone() 方法:

Orange orange1 = new Orange("桔子", 0.3);
try {
    Orange orange2 = orange1.clone();
    System.out.println("orange1: " + orange1);
    System.out.println("orange2: " + orange2);
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

运行结果如下:

orange1: com.example.Orange@15db9742
orange2: com.example.Orange@6d06d69c

可以看到返回的两个对象的 hashcode 不同,说明这两个对象实际上是两份不同的副本。经过 clone() 之后,orange1 和 orange2 两个橘子类的实例相同,但内存地址不同,互相独立,修改 orange1 的属性不会影响 orange2。

其他注意事项

由于 Object 类的 clone() 方法访问限制比较高,我们在使用时,有另外的三种可以使用的 clone 方法,分别是:

  • 浅拷贝;
  • 深拷贝;
  • 序列化拷贝。

在具体开发中,可以根据实际需要选择不同的拷贝方式。

示例说明

浅拷贝示例

浅拷贝的对象引用属性不进行克隆,新建对象中的属性引用与原始对象中的属性引用是相同的。如:

public class Apple implements Cloneable {
    private String name;
    private Double weight;
    private Date date;

    public Apple(String name, Double weight, Date date) {
        this.name = name;
        this.weight = weight;
        this.date = date;
    }

    public String getName() {
        return name;
    }

    public Double getWeight() {
        return weight;
    }

    public Date getDate() {
        return date;
    }

    @Override
    public Apple clone() throws CloneNotSupportedException {
        return (Apple) super.clone();
    }
}

public class Cook {
    public static void main(String[] args) {
        try {
            Apple apple1 = new Apple("红苹果", 0.5, new Date());
            Apple apple2 = apple1.clone();

            System.out.println("apple1: " + apple1);
            System.out.println("apple2: " + apple2);
            System.out.println("是否是同一对象: " + (apple1 == apple2));
            System.out.println("apple1.name: " + apple1.getName());
            System.out.println("apple2.name: " + apple2.getName());
            System.out.println("是否是同一对象: " + (apple1.getName() == apple2.getName()));
            System.out.println("apple1.date: " + apple1.getDate());
            System.out.println("apple2.date: " + apple2.getDate());
            System.out.println("是否是同一对象: " + (apple1.getDate() == apple2.getDate()));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

apple1: com.example.Apple@15db9742
apple2: com.example.Apple@6d06d69c
是否是同一对象: false
apple1.name: 红苹果
apple2.name: 红苹果
是否是同一对象: true
apple1.date: Thu Nov 19 14:22:14 CST 2020
apple2.date: Thu Nov 19 14:22:14 CST 2020
是否是同一对象: true

深拷贝示例

深拷贝是指完全克隆一个对象,即属性引用与原始对象中的属性引用不是相同的,而是新建的。如:

public class Banana implements Cloneable {
    private String name;
    private Double weight;
    private Orange orange;

    public Banana(String name, Double weight, Orange orange) {
        this.name = name;
        this.weight = weight;
        this.orange = orange;
    }

    public String getName() {
        return name;
    }

    public Double getWeight() {
        return weight;
    }

    public Orange getOrange() {
        return orange;
    }

    @Override
    public Banana clone() throws CloneNotSupportedException {
        Banana banana = (Banana) super.clone();
        banana.orange = orange.clone();
        return banana;
    }
}

public class Cook {
    public static void main(String[] args) {
        try {
            Orange orange = new Orange("桔子", 0.3);
            Banana banana1 = new Banana("香蕉", 0.2, orange);
            Banana banana2 = banana1.clone();

            System.out.println("banana1: " + banana1);
            System.out.println("banana2: " + banana2);
            System.out.println("是否是同一对象: " + (banana1 == banana2));
            System.out.println("banana1.orange: " + banana1.getOrange());
            System.out.println("banana2.orange: " + banana2.getOrange());
            System.out.println("是否是同一对象: " + (banana1.getOrange() == banana2.getOrange()));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

banana1: com.example.Banana@15db9742
banana2: com.example.Banana@6d06d69c
是否是同一对象: false
banana1.orange: com.example.Orange@7852e922
banana2.orange: com.example.Orange@4e515669
是否是同一对象: false

序列化拷贝示例

使用序列化拷贝可以将对象进行二进制序列化,然后再将序列化后的二进制数据反序列化为一个新的对象。如:

public class Watermelon implements Serializable {
    private String name;
    private Double weight;

    public Watermelon(String name, Double weight) {
        this.name = name;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public Double getWeight() {
        return weight;
    }
}

public class Cook {
    public static void main(String[] args) {
        Watermelon watermelon1 = new Watermelon("西瓜", 5.0);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(watermelon1);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Watermelon watermelon2 = (Watermelon) ois.readObject();

            System.out.println("watermelon1: " + watermelon1);
            System.out.println("watermelon2: " + watermelon2);
            System.out.println("是否是同一对象: " + (watermelon1 == watermelon2));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

watermelon1: com.example.Watermelon@15db9742
watermelon2: com.example.Watermelon@6d06d69c
是否是同一对象: false

总结

以上就是Java中clone()的使用方法,可以实现对象的拷贝功能。当然,使用时也要注意一些细节问题,根据实际场景选择对应的拷贝方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java 中clone()的使用方法 - Python技术站

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

相关文章

  • Spring FreeMarker整合Struts2过程详解

    下面是“Spring FreeMarker整合Struts2过程详解”的完整攻略: 1. 初步准备 在项目中引入Spring和Struts2框架; 引入FreeMarker模板引擎。 2. 添加Spring配置文件 在Spring配置文件中,需要添加以下内容: <!– 引入FreeMarker视图解析器 –> <bean id=&quo…

    Java 2023年5月20日
    00
  • 利用apache ftpserver搭建ftp服务器的方法步骤

    当您想要在本地或远程计算机上快速共享文件时,FTP服务器是一种非常有用的工具。Apache FTP服务器是一个优秀的FTP软件,拥有强大的安全功能,易于配置。 以下是利用Apache FTP服务器搭建FTP服务器的步骤,包括Linux和Windows系统。 在Linux上安装Apache FTP服务器 首先,确保Java已经安装。可以在命令行中运行 java…

    Java 2023年6月2日
    00
  • 详解CentOS7.0安装与配置Tomcat-7

    下面是详解CentOS7.0安装与配置Tomcat-7的完整攻略: 安装Java 使用yum安装Java: sudo yum install java 验证Java是否安装成功: java -version 下载与安装Tomcat 下载Tomcat7: wget https://mirror.bit.edu.cn/apache/tomcat/tomcat-7…

    Java 2023年5月19日
    00
  • weblogic服务建立数据源连接测试更新mysql驱动包的问题及解决方法

    WebLogic服务建立数据源连接测试 为了使WebLogic Server能够连接到数据库中的数据,您需要在WebLogic Server上设置数据源。以下是设置数据源的步骤: 步骤1:登录WebLogic控制台 首先,您需要打开WebLogic Server的管理控制台。在Web浏览器中输入URL(如http://localhost:7001/conso…

    Java 2023年5月20日
    00
  • 简析Java中的util.concurrent.Future接口

    简析Java中的util.concurrent.Future接口 java.util.concurrent.Future是Java中实现异步操作和并发编程的一个核心接口,它的主要作用是提供一个机制,允许异步任务返回一个结果和处理异常,这个结果将在未来的某个时间点通过Future对象来获取。即,当我们发起一个异步请求后,系统会立即返回一个Future对象,通过…

    Java 2023年5月25日
    00
  • Java Pattern与Matcher字符串匹配案例详解

    Java Pattern与Matcher字符串匹配案例详解 一、背景介绍 在Java中,支持字符串的正则匹配。在字符串中,可以使用\d表示数字,\w表示字母数字下划线,\s表示空格或换行符等等特殊字符。而Java中提供了Pattern和Matcher类,用来实现正则表达式的匹配操作。 二、Pattern类 Pattern类是正则表达式编译后的表示形式。在Ja…

    Java 2023年5月23日
    00
  • window系统安装jdk jre的教程图解

    下面是“Window系统安装JDK/JRE的教程图解”的完整攻略: 安装JDK/JRE 1. 下载JDK/JRE 首先,前往Oracle官网的JDK下载页面:https://www.oracle.com/java/technologies/javase-downloads.html 根据需要下载对应版本的JDK/JRE安装包,选择相应的操作系统,比如Wind…

    Java 2023年5月24日
    00
  • MyBatis插件机制超详细讲解

    MyBatis插件机制超详细讲解 什么是MyBatis插件机制 MyBatis插件机制指的是MyBatis框架提供了一种扩展机制,可以在执行SQL语句的各个环节进行拦截,并在拦截到这些环节时进行自定义的操作,以实现更自定义的功能,例如SQL日志拦截、自定义SQL追踪、自定义SQL执行等。 插件机制最主要的功能是拦截方法并执行自定义操作。 MyBatis插件机…

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