• 关于JAVA核心技术(卷一)读后的思考(回调,clone的讨论)


    回调

    回调是一种常见的程序设计模式。这种模式中,可以指出某个特定事件发生时应该采取的动作。

    直接给上代码

    package com.java.timer;
    
    import java.awt.event.ActionListener;
    
    import javax.swing.JOptionPane;
    import javax.swing.Timer;
    
    public class TimerTest {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ActionListener listener=new TimePrinter();
            Timer t = new Timer(10000,listener);
            t.start();
            JOptionPane.showMessageDialog(null, "Quit program?");
            System.exit(0);
            
    
        }
    
    }
    package com.java.timer;
    
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    
    public class TimePrinter implements ActionListener {
    
        @Override
        public void actionPerformed(ActionEvent event) {
            // TODO Auto-generated method stub
            System.out.println("At the tone,the time is "+new Date());
            Toolkit.getDefaultToolkit().beep();
        }
    
    }

    这里调用了java.swing包中的Timer类,可以使用它在给定的时间间隔时发出通告

    我们这里可以分析下这段代码。构造一个TimePrinter类调用ActionListener接口,而这个类对这个方法的实现,是通过构造Date对象,紧接着调用静态方法deep()进行提示。

     ActionListener listener=new TimePrinter();
    这个语句的意思是声明一个接口类型的变量,然后new一个TimePrinter对象。利用接口型变量对其存储。

    紧接着利用Timer方法构造一个定时器,调用接口变量为其中之一的参数,最后调用JOptionPane()方法来构造一个对话框,整个过程就完成了。

    这个过程就体现出了回调这个设计模式的思想。在后面的博客中我应该会总结Java的设计模式。

    对象克隆

    这里要说到对象克隆的知识了。这里我们就会讨论一个Cloneable接口,这个接口只是一个类提供了一个安全的clone()方法。

    这里可以举个例子,

    Employee original = new Employee("John Public",50000);
    Employee copy =original;
    copy.raiseSalary(10);

    我们来分析一下这段代码,第一句new了一个Employee对象,将对象存储地址保存在original中,而第二句则将original中存储的对象复制了一份到copy变量中去了,这样的话original和copy指向的都是同一个地址,也就是那个实例地址存储在这两个变量中,所以第三句对copy进行修改,同时也对original进行修改了。

    而我们希望拷贝一份与原来无关的变量,那这样就要用到clone方法了。

    Employee original = new Employee("John Public",50000);
    Employee copy = original.clone();
    copye.raiseSalary(10);

    clone方法是Object的一个protect方法,说明代码不能直接调用这个方法,只有子类或者相同的类才可以克隆父类对象。这个限制是有原因的,我们可以从Object如何实现clone方法来想。因为其对这个对象是一无所知的,只能逐个域的进行拷贝。

    这里我们就要讨论一下clone的分类:

    它分为深拷贝浅拷贝

    默认的克隆操作是“浅拷贝”,浅拷贝有什么影响,是要看具体情况的,如果原对象和浅克隆对象共享的子对象是不可变的,那么这种共享就是安全的。如果子对象属于一个不可变的类,如String,简而言之,就是所有的量不可改变的量是,浅拷贝是安全的。如果存在可变的量,就要对clone方法建立一个深拷贝。

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

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

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

    3)是否不该使用clone;

    如果一个对象请求克隆,但并没有实现这个接口,就会生成一个受查异常。Cloneable接口是Java提供的一组标记接口之一,正常接口一般是确保一个类实现一个或一组特定的方法。标记接口不包含任何方法,它唯一的作用是允许在类型查询中使用instanceof。即使浅拷贝实现能满足要求,但还是要实现Cloneable接口,将clone重新定义为public,再调用super.clone()。

    代码:

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

    与Object.clone提供的浅拷贝相比,前面看到的方法并没有增加任何功能,只是将其设为公有的。要建立深拷贝,需要更多工作,克隆对象中可变的实例域。

    下面是一个例子:

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

    如果都在一个对象上调用clone,但这个对象的类并没有实现Cloneable,这个clone方法就会抛出一个异常。虽然Employee和Date类实现了Clone接口,但是编译器并不知道,所有直接throws这个异常。

    这里要注意一个问题,就是子类的克隆,假设我们已经定义了Employee类的clone方法,这时候,就要知道,任何人都会用它来克隆Manager,这时候就要取决于Manager的域了,如果增加的域都是基本数据类型或者是不可变类,那就没有问题,如果不是的话,那就需要重新定义clone方法。

    总而言之,其实很简单,浅拷贝就是默认拷贝,不需要克隆对象中的可变实例域,只需要将clone方法定义为public类型就可以了

    深拷贝就是需要重新定义clone()方法,使可变类实现拷贝,两者都要对其进行异常处理。

    如果有写的不对的地方,欢迎指正,希望能够共同进步,谢谢!
  • 相关阅读:
    每天一个linux命令(9):touch 命令
    每天一个linux命令(8):cp 命令
    面试
    [HTML]页面间传值的五种方法
    [thml]HTML select标签 获取选中的option的value及Text内容
    [HTML]js定时器使用 setInterval
    [HTML]表格的一切
    [HTML]HTML框架IFrame下利用JS在主页面和子页面间传值
    [HTML]js实现页面跳转,页面A跳到另一个页面B.以及页面传值(中文)
    [HTML][服务器]状态码列表status
  • 原文地址:https://www.cnblogs.com/zzuzhouxiang/p/10354252.html
Copyright © 2020-2023  润新知