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。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Linux正确删除软连接[通俗易懂]

    在Linux上删除软连接不要使用rm-rf!!!在Linux上删除软连接不要使用rm-rf!!!在Linux上删除软连接不要使用rm-rf!!!因为如果使用rm-rflinkName的方式,如果不小心在目录后面加了“/”,或者按了Tab键补全,执行之后会删除源目录文件。如果要使用rm-rflinkName的时候一定要注意源、目标文件或目录都不要在后面加…

  • 3极管的原理_二极管讲解

    3极管的原理_二极管讲解我们把晶体管比作两个二极管时候,是指基极-射极二极管和基极-集电极二极管。NPN型二极管与PNP型二极管对三极管放大作用的理解,切记一点:能量不会无缘无故的产生,所以,三极管一定不会产生能量。但三极管厉害的地方在于:它可以通过小电流控制大电流。放大的原理就在于:通过小的交流输入,控制大的静态直流。假设三极管是个大坝,这个大坝奇怪的地方是,有两个阀门,一个大阀门,一个小阀门。小阀门可以用…

    2022年10月21日
  • python 拼接字符串字作为字符串使用(python连接字符串)

    Python字符串拼接数字的方法发布时间:2020-08-0515:40:44来源:亿速云阅读:99作者:小新这篇文章将为大家详细讲解有关Python字符串拼接数字的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Python字符串拼接数字在某些特殊场景中,我们需要将字符串与数字进行拼接,而Python不允许直接拼接数字和字符串,程序必须先将数字转换成字…

  • c语言贪吃蛇源代码简单_java贪吃蛇源码

    c语言贪吃蛇源代码简单_java贪吃蛇源码所用知识:一维数组的使用结构体的使用播放音乐函数的使用电脑按键的检测窗口光标坐标函数的使用相关函数讲解1.光标移动到某一指定坐标的函数#include<windows.h>//坐标的APIvoidgotoxy(intx,inty){ HANDLEhandle=GetStdHandle(STD_OUTPUT_HANDLE); COORDco…

  • 实时数据库与时序数据库区别_时间序列数据库

    实时数据库与时序数据库区别_时间序列数据库1、概述在工业大数据数据库存储领域,除了传统的关系型数据库和分布式数据库以外,还有一种类型的数据库是非常常用,而且是非常有必要的,就是实时数据库,以及时序数据库。但是,大家可能会有疑问,都是专门处理时序数据的,这是两种数据库吗?他们之间有什么联系?1.1发展历史实时数据库是数据库系统的一个分支,它适用于处理不断更新的快速变化的数据及具有时间限制的事务处理。实时数据库技术是实时系统和数据库技术相结合的产物。实时数据库最起初是基于先进控制和优化控制而出现的,对数据的实时性要求比较高,因而实时、高效

  • Selenium面试题

    Selenium面试题NO.1Selenium是什么是一个开源的web自动化测试的框架,支持多种编程语言,支持跨浏览器平台进行测试NO.2Selenium中有哪些验证点?Selenium主要有三种验证点检查页面标题检查某些文字检查某些元素(文本框,下拉菜单,表等)NO.3你如何从Selenium连接到数据库?Selenium是一个WebUI自动化工具。它不提供任何API来建立数据库连接。这取决于你使用Selenium进行自动化的编程语言。NO.4如何提高selenium脚本的执行速度?1.优

发表回复

您的电子邮箱地址不会被公开。

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