当前位置: 首页 > news >正文

《Java核心技术 卷I》对象克隆

对象克隆

讨论Cloneable接口,指示一个类提供了一个安全的clone方法。

对象引用建立副本,任何一个变量改变都会影响另一个变量。

如果希望copy一个新对象,初始状态相同,但之后它们各自会有自己不同的状态,这种情况可以使用clone方法。

如果数据域都是数值或其他基本类型,拷贝这些域没有任何问题,但是包含子对象的引用,拷贝域就会得到相同对象的另一个引用,这样一来,原对象和克隆对象仍然会共享一些信息。

以下这种克隆就是浅拷贝,并没有克隆出生日期对象。如果原对象与浅拷贝对象共享子对象不可变,那共享就是安全的。

不过,通常子对象都是可变的,必须重新定义clone方法来建立一个深拷贝,同时克隆出所有子对象。

    package corejava;import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Objects;public class EmployeeTest {public static void main(String[] args) throws CloneNotSupportedException {Employee e = new Employee("孙悟空", 75000,1987,12,15);Employee e1 = (Employee) e.clone();System.out.println(e==e1);System.out.println(e.equals(e1));System.out.println(e.hashCode()==e1.hashCode());System.out.println(e.getHireDay()==e1.getHireDay());//结果false,true,false,true,总结来说就是浅拷贝,出生日期不该是同一对象。      }}
class Employee implements Comparable<Employee>,Cloneable {//实例字段private String name;private double salary;private Date hireDay;int percent = 10;//构造器public Employee(String n,double s,int year,int month, int day) {name = n;salary = s;GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);hireDay = calendar.getTime();}public Employee() {}//public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireDay() {return hireDay;}public void setHireDay(Date hireDay) {this.hireDay = hireDay;}public void raiseSalary(Employee e) {e.percent = 15;double raise = salary * e.percent /100;salary += raise;}@Overridepublic boolean equals(Object otherObject) {super.equals(otherObject);
//        if(this==otherObject) return true;if(otherObject==null) return false;if(getClass()!=otherObject.getClass()) return false;Employee other = (Employee) otherObject;return this.name.equals(other.name)&&this.salary==other.salary&&Objects.equals(this.hireDay, other.hireDay);}@Overridepublic int compareTo(Employee o) {return Double.compare(getSalary(), o.getSalary());}@Overrideprotected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();}
}

对于每一个类,需要确定:

  • 默认的clone方法是否满足要求。
  • 是否可以在可变的子对象上调用clone来修补默认的clone方法。
  • 是否不该使用clone。

实际上第3个选项是默认选项,如果选择第1项或第2项,类必须:

  • 实现Cloneable接口。
  • 重新定义clone方法,并指定public访问修饰符。

不实现接口,无法克隆,会报错,可以把克隆接口看成一个标识,当前类所实现的接口数组中包括克隆接口,那么虚拟机执行克隆动作。

注释:Cloneable接口是Java提供的一组标记接口(tagging interface)之一,也称为记号接口(marker interface)。它不包含任何方法,唯一作用就是允许类型查询中使用instanceof,建议你自己的程序中不要使用标记接口。

上面代码改为深拷贝的案例:

    //深拷贝public Employee clone() throws CloneNotSupportedException{Employee cloned = (Employee) super.clone();cloned.hireDay = (Date) hireDay.clone();return cloned;}

所有数组都有clone方法用来建立一个新数组。


http://www.mrgr.cn/news/67598.html

相关文章:

  • 移动应用开发 实验二:标准身高计算器
  • 【Web前端】OOP编程范式
  • 实习冲刺Day15
  • Echats柱状图的横坐标用图片显示
  • 基于MATLAB的运动车辆跟踪检测系统
  • Rust闭包(能够捕获周围作用域变量的匿名函数,广泛应用于迭代、过滤和映射)闭包变量三种捕获方式:通过引用(不可变引用)、通过可变引用和通过值(取得所有权)
  • 三周精通FastAPI:35 最常用的模板引擎Jinja2
  • scala list系列
  • Sigrity Power SI 3D-EM Capacitance Extraction模式如何进行电容的提取操作指导
  • 打印等边三角形和直角三角形(用循环)C语言
  • 红黑树详解
  • 史上最大应用层DDoS攻击 H2 Rapid Reset攻击研究
  • 什么是大模型?一文读懂大模型的基本概念
  • 基于Zynq FPGA对雷龙SD NAND的测试
  • MySQL数据库面试题(上)
  • 后端Node学习项目-项目基础搭建
  • pip包离线下载地址
  • swiper分页器自定义
  • wxwidgets开发最佳IDE之codeLite配置,比CodeBlocks好用10倍,还支持Qt和VS,web开发
  • map容器的设计理念
  • Verilog基础知识-数字进制格式
  • Facebook vs. Google:哪个更适合你的品牌
  • 第十一天 线性代数基础
  • GPU的内存是什么?
  • 【SpringCloud】Kafka消息中间件
  • AI大模型如何重塑软件开发流程?