6.2.3   对象克隆

Cloneable 接口,这个接口指示一个类提供了一个安全的clone方法。(稍作了解)

为一个对象引用的变量建立副本时,原变量和副本都是同一个对象的引用,任何一个变量改变都会影响另一个变量。

Employee original =new Employee("John Public",50000);
Employee copy=original;
copy.raiseSalary(10);//(加工资的一个方法)

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

Employee copy =original.clone();
copy.raiseSalary(10);(original没有改变)

对于一个类,需要确定:

1)默认的clone方法是否满足要求;

2)是否可以在可变的子对象上调用clone来修补默认的clone方法;

3)是否不该使用clone。(默认选项)

如果选择了第一项或第二项,类必须:

1)实现Cloneable接口;

2)重新定义clone方法,并指定public访问修饰符。

Cloneable接口是java提供的一组标记接口(tagging interface)之一。或者称之为标记接口(marker interface)。接口的通常用途是确保一个类实现一个或一组特定的方法。标记接口不包含任何方法,他唯一的作用就是允许在类型查询中使用instanceof

即使clone的默认(浅拷贝)实现能够满足要求,还是需要实现Cloneable接口,将clone重新定义为public,在调用super.clone()。下面给出一个例子:

class Employee implements Cloneable
{
public Employee clone() throws CloneNotSupportedException
{
return (Employee) super.clone();
}
}

要建立深拷贝,(克隆对象中可变的实例域)

class Employee implements Cloneable
{
public Employee clone() throws CloneNotSupportedException
{
Employee cloned=(Employee) super.clone();
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
}

下列程序克隆了Employee类的一个实例,然后调用两个更改器方法。raiseSalary方法会改变salary域的值,而setHireDay方法改变hireDay域的状态,这两个更改器方法都不会影响原来的对象,因为clone建立了一个深拷贝。

 package cc.openhome;
import java.util.Date;
import java.util.GregorianCalendar;
public class CloneTest {
public static void main(String[] args) {
try {
Employee original =new Employee("mama", 80000);
original.setHireDay(2018, 3, 19);
Employee copy=original.clone();
copy.raiseSalary(10);
copy.setHireDay(2008, 8, 8);
System.out.println("original="+original);
System.out.println("copy="+copy);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
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();
}
public Employee clone() throws CloneNotSupportedException
{
Employee cloned=(Employee) super.clone();
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();
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+"]";
}
}
original=Employee[name=mama,salary=80000.0,hireDay=Mon Mar 19 00:00:00 CST 2018]
copy=Employee[name=mama,salary=88000.0,hireDay=Fri Aug 08 00:00:00 CST 2008]
成功构建 (总时间: 0 秒)

run:

java 核心技术卷一笔记 6 .2.3 接口 lambda 表达式 内部类的更多相关文章

  1. Java核心技术卷一 · 笔记(2)

    目录 1.多态.动态绑定 2.覆盖 3.阻止继承:final 类和方法 4.抽象类(abstract修饰) 5. 4 个访问修饰符: 6.toString() 7.对设计继承关系很有帮助的建议 8.接 ...

  2. java 核心技术卷一笔记 6 .2接口 lambda 表达式 内部类

    6.2 接口实例 6.2.1 接口与回调 在java.swing包中有一个Timer类,可以使用它在到达给定的时间间隔时发出通告,假如程序中有一个时钟,就可以请求每秒钟获得一个通告,以便更新时钟的表盘 ...

  3. java 核心技术卷一笔记 6 .1接口 lambda 表达式 内部类

    6.1 接口不是类,是对类的一组需求的描述,这些类需要遵守接口描述的统一格式进行定义.例如:Arrays类中sort方法(可以对对象数组进行排序)前提是对象所属的类必须实现了Comparable 接口 ...

  4. java 核心技术卷一笔记 6 .1.接口 lambda 表达式 内部类

    6.1.2 接口不是类,不能实例化一个接口:但是可以声明接口的变量:Comparable x;    接口变量必须引用实现了接口的类对象:x = new Employee(); 检查一个对象是否属于某 ...

  5. java核心技术卷一笔记(1)

    jdk是java开发工具包,里面包含了javac.jar.javadoc.java等工具,可以在bin目录中找到.有一个文件夹是jre,即jdk也包含了java运行环境.jre可单独安装,只是运行ja ...

  6. Java核心技术卷一 · 笔记(1)

    目录 1.java的关键术语 2.==和equals 3.空串与 Null 串 4.构建字符串 5.封装 6.对象的三个主要特性 7.依赖(dependence).聚合(aggregation).继承 ...

  7. java核心技术卷一笔记(2)

    ---恢复内容开始--- 异常.断言 所有的异常都继承自Throwable类,异常包括已检查异常和未检查异常,应该抛出已检查异常,而未检查异常要么是不可控的(Error),要么是应该避免发生的(Run ...

  8. 【阅读笔记】Java核心技术卷一 #0

    这是一篇备忘性质的读书笔记,仅记录个人觉得有用的知识点 本文作为一个目录索引,部分章节跳过 吐槽:此书中文翻译有不少地方不太通顺,这种情况我要把英文版对应的部分也读一遍才能明白(说实话,英文里的从句表 ...

  9. 对《Java核心技术卷一》读者的一些建议

    <Java核心技术卷一>是唯一可以和<Java编程思想>媲美的一本 Java 入门书.单从技术的角度来看,前者更好一些.但上升到思想层面嘛,自然后者更好,两者的偏重点不同. 思 ...

随机推荐

  1. Flask_restful 插件实战笔记——基本概念与使用

       最近在Resetful接口设计上想法还是挺多的,也实现了一些需求!想着整理下Flask_restful插件的基本知识,方便日后的复习!   官方地址:https://flask-restful. ...

  2. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs&qu ...

  3. 割点(Tarjan算法)

    本文可转载,转载请注明出处:www.cnblogs.com/collectionne/p/6847240.html .本文未完,如果不在博客园(cnblogs)发现此文章,请访问以上链接查看最新文章. ...

  4. Tomcat 容器的安全认证和鉴权

    大量的 Web 应用都有安全相关的需求,正因如此,Servlet 规范建议容器要有满足这些需求的机制和基础设施,所以容器要对以下安全特性予以支持: 身份验证:验证授权用户的用户名和密码 资源访问控制: ...

  5. (转载) 车牌识别EasyPR--开发详解

    车牌识别EasyPR--开发详解 http://blog.csdn.net/liuuze5/article/details/46290455 源码GitHub:https://github.com/l ...

  6. CodeForces Canada Cup 2016【A,B,C,D】

    CodeForces 725A: 思路就是如果"最左"不是'>'这个了,那么这个右边的一定不可能到达左边了: 同理最右: CodeForces 725B: 有两个空姐,一个从 ...

  7. CentOS Linux 7 提示 lsof: 未找到命令

    我们常使用 lsof -i:端口号 命令来查看某端口是否开放,如使用下面的命令,查看8080端口: lsof -i: 结果: 提示:lsof:未找到命令 解决办法 使用yum来安装lsof,命令如下: ...

  8. Node.js 内置模块Stream(流)

    "流"是一种抽象的数据结构 通过使用"流"可以将一段数据分割成几段,并按顺序传输,使用"流"可以降低对系统性能的要求,减少对CPU的消耗 S ...

  9. 计算机网络自顶向下方法第3章-传输层 (Transport Layer).1

    3.1 概述和运输层服务 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信(logic communication)功能. 3.1.1 运输层和网络层的关系 网络层提供了主机之间的逻辑通信,而 ...

  10. bzoj 5449 序列

    https://www.lydsy.com/JudgeOnline/problem.php?id=5449 话说很早以前做过..算是IDA*的板子吧,一个简单的估价函数就可以过去了 %:pragma ...