java cloneable 接口_Cloneable 接口 记号接口(标记接口)「建议收藏」

java cloneable 接口_Cloneable 接口 记号接口(标记接口)「建议收藏」Cloneable接口指示了一个类提供了一个安全的clone方法。首先了解Object.clone()方法:clone是Object超类的一个protected方法,用户代码不能直接调用这个方法。Object的子类只能调用Object超类中受保护的clone方法来克隆它自己的对象,必须重新定义clone为public才能允许所有方法调用这个类的实例的clone方法克隆对象。clone方法的作用:…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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

首先了解Object.clone()方法:

clone是Object超类的一个protected方法,用户代码不能直接调用这个方法。Object的子类只能调用Object超类中受保护的clone方法来克隆它自己的对象,必须重新定义clone为public才能允许所有方法调用这个类的实例的clone方法克隆对象。

clone方法的作用:clone方法对Employee调用它对这个对象一无所知,所以只能逐个域地进行拷贝。a. 如果对象中的所有数据域都是数值或者其他基本类型,拷贝这些域没有问题;b. 但是如果对象中包含子对象的引用,拷贝域就会得到相同子对象的另一个引用(浅拷贝)。这样一来,原对象和克隆的对象仍然会共享一些信息。

浅拷贝的影响:如果原对象和浅克隆对象共享的子对象是不可变的,那么这种共享就是安全的。如果子对象属于一个不可变的类,如String,就是这种情况。或者在对象的生命周期中,子对象一直包含不变的常量,没有更改器会改变它,就是没有方法会生成它的引用,这种情况同样是安全的(举个栗子:下面例子中hiereDay是一个Date对象,Date类的域是可变的,所以hireDay需要深拷贝。而LocalDate的域不可变,如果hireDay是不可变的LocaDate类的一个实例,就无需我们做任何处理了)。

public class Employee implements Cloneable {

private String name;

private double salary;

private Date hireDay;

public Employee(String name, double salary)

{

this.name = name;

this.salary = salary;

hireDay = new Date();

}

@Override

public Employee clone() throws CloneNotSupportedException

{

// call Object.clone() Employee cloned = (Employee) super.clone(); // clone会逐个域的进行拷贝

// clone mutable fields cloned.hireDay = (Date) hireDay.clone();

return cloned;

}

public void setHireDay(int year, int month, int day)

{

Date newHireDay = new GregorianCalendar(year, month – 1, day).getTime();

// Example of instance field mutation hireDay.setTime(newHireDay.getTime());

}

public void raiseSalary(double byPercent)

{

double raise = salary * byPercent / 100;

salary += raise;

}

public String toString()

{

return “Employee[name=” + name + “,salary=” + salary + “,hireDay=” + hireDay + “]”;

}

}

public class Main {

public static void main(String[] args)

{

Employee employee = new Employee(“jack1”, 20000);

try {

Employee clone = employee.clone();

employee.raiseSalary(20);

employee.setHireDay(2020, 10, 22);

System.out.println(employee.toString());

System.out.println(clone.toString());

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

/*** 输出:Employee[name=jack1,salary=24000.0,hireDay=Thu Oct 22 00:00:00 CST 2020]Employee[name=jack1,salary=20000.0,hireDay=Sun Oct 13 17:47:26 CST 2019]*/

再看一个栗子,hireDay为不可变LocalDate类的实例时(private LocalDate hireDay;),Main.java类代码基本不变(构造函数有改变 -> Employee employee =newEmployee(“jack1”,20000,2019,10,13);):

public class Employee implements Cloneable {

private String name;

private double salary;

private LocalDate hireDay;

public Employee(String name, double salary, int year, int month, int day)

{

this.name = name;

this.salary = salary;

hireDay = LocalDate.of(year, month, day);

}

@Override

public Employee clone() throws CloneNotSupportedException

{

// call Object.clone() Employee cloned = (Employee) super.clone();

// // clone mutable fields// cloned.hireDay = (Date) hireDay.clone();

return cloned;

}

public void setHireDay(int year, int month, int day)

{

// Date newHireDay = new GregorianCalendar(year, month – 1, day).getTime();// // Example of instance field mutation// hireDay.setTime(newHireDay.getTime()); hireDay = LocalDate.of(year, month, day);

}

public void raiseSalary(double byPercent)

{

double raise = salary * byPercent / 100;

salary += raise;

}

public String toString()

{

return “Employee[name=” + name + “,salary=” + salary + “,hireDay=” + hireDay + “]”;

}

}

对于一个要实现clone方法的类,需要确定:实现Cloneable接口;

重新定义clone方法,并且制定public访问修饰符。

注意:

Cloneable接口的出现与接口的正常实现没有关系。具体讲,它(Cloneable接口)没有指定clone方法,这个方法是从Object类继承的(应该是实现接口的类从Object类继承)。Cloneable接口的作用只是作为一个标记,指示 类设计者 了解克隆过程。对象对于克隆很“偏执”,如果一个对象请求克隆,但没有实现这个接口,就会生成一个受查异常(报错:java.lang.CloneNotSupportedException)。

Cloneable接口是Java提供的一组标记接口(tagging interface)之一。有些程序员也称之为记号接口(marker interface)。注意:Comparable等接口的通常用途是确保一个类实现一个或一组特定的方法。标记接口不包含任何方法,它唯一的作用就是允许在类型查询中使用instanceof:

if (obj instanceof Cloneable) ..

建议自己程序中不要使用标记接口。

即使clone的默认(浅拷贝)实现能够满足要求,还是需要实现Cloneable接口,将clone方法重新定义为public,再调用super.clone()。

class Employee implements Cloneable()

{

// raise visibility level to public, change return type public Employee clone() throws CloneNotSupportedException

{

return (Employee) super.clone();

}

}

如果一个类重写了clone方法,但是类没有声明实现接口 implements Cloneable,类会抛出一个CloneNotSupportedException异常。当然,Employee和Date类实现了Cloneable接口,所以不会抛出这个异常。不过编译器不会了解这一点,所以我们声明了这个异常:

public Employee clone() throws CloneNotSupportedException

这样,子类在不支持克隆时选择抛出一个CloneNotSupportedException异常。

clone没有想象中的那么常用,标准库中只有5%的类实现了clone。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/184369.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C语言中scanf函数详解「建议收藏」

    C语言中scanf函数详解「建议收藏」scanf函数  上一节中我们讨论了,如何将整数,浮点数,字符串打印到屏幕上去。既然有输出,怎么能没有输入呢?这一节中,我们来介绍与printf相反的scanf函数。  scanf的功能是将键盘输入的字符串转换成整数、浮点数、字符或字符串。1.scanf函数的使用公式scanf是一个变参函数。(参数的数量和类型不确定)scanf的第一个参数是字符串。scanf的第一个参数是需要输入的字符串以及需要被读取的占位符。scanf的后续参数,是依次被读取并赋值的变量地址。占位符的类型和数量需要与

    2025年6月30日
    2
  • 几种测试技术

    几种测试技术一、单元测试技术1.定义:单元测试又称为模块测试(程序测试),即集中力量来检验软件设计的最小单位——模块。       单元测试(unittesting),是指对软件中的最小可测试单元进行检查和验证。2.目的:单元测试的目的在于发现各模块内部可能存在的各种差错。3.内容/任务:    (1)模块接口测试(单元测试的基础):当模块通过外部设备进行输入/输出…

    2022年9月18日
    1
  • 一种基于Linux文件系统的数据恢复方法_武汉病例轨迹

    一种基于Linux文件系统的数据恢复方法_武汉病例轨迹问题阶段起因:昨天晚上思路不是很清晰(上了一天班回来有点蒙),还是强忍着疲惫想搞事情,结果悲剧了……本来想拿SD卡做一张linux烧录卡,烧录脚本是很久以前写的,有git记录,一直不成功,就回退了几次提交,然后执行的时候没有给脚本传参(/dev/sd**),结果脚本中默认磁盘设备为/dev/sdb,在现在电脑上是一块数据磁盘,执行到一半的时候由于某些原因意外退出,但还是有一些命令执行,比

    2025年5月30日
    2
  • django drf_django 消息队列

    django drf_django 消息队列前言我们上篇文章使用到了Serializer类,可能有小伙伴说太过复杂,那么本篇就为大家带来更加简便的序列化类ModelSerializerModelSerializer先来看下ModelSer

    2022年7月31日
    8
  • 金山词霸2007升级v10.0.0.4

    金山词霸2007升级v10.0.0.4词霸2007不但产品功能更加完善,而且在用户的体验方面也做了很多改进。首先,词霸07收录了150余本权威词典,70余个专业词库,同时支持28种常备资料线实时更新,让您随时拥有奥运知识、常用工具(货币单位等)等最新的资料;其次全面支持简体中文、英文、日文查词功能,满足更多用户需求;值得一提的是,词霸07收录了与朗文、牛津、韦氏齐名四大词典的《美国传统词典》最新版,英汉、英英双解,包含96000余词条

    2022年7月15日
    18
  • Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

    Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

    2022年2月1日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号