zoukankan      html  css  js  c++  java
  • Java—内部类(二)—实现闭包与回调


    Java—内部类(二)—实现闭包与回调

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yuwenhao07/article/details/53607117
    前言:
    Java的闭包与回调我也是第二次接触这个概念,之前在自学Android的时候绘制View很多地方都用到了监听器回调,一直不是很明白,现在回头巩固Java的基础总算的弄明白,尽量用我自己理解的语言来和大家分享,希望对不懂的朋友可以有一定的帮助,大神也可以给我一点指点。

    概念:
    我觉得在理解一个事物之前,需要对这个事物在我们的大脑里有一个初步的概念,然后再对这个概念补充上细节,这是我在理解一些陌生事物的时候的一个方法,也可以说是类比理解法吧。先说闭包~

    一.闭包
    闭包,故名思意就是,把一个包关起来,那么对于Java来说,这个包就是类了,因为在java中任何事物都是类,都是对象。那么闭包,直接理解上就是把一个类封装起来(封装就是包装差不多的意思)。然后结合一下,闭包内容放在内部类中,所以闭包就是用一个类把另一个类包装起来,说起来这和内部类没有什么不同点啊,为啥要专门用一个词来表述它呢?因为这个闭包还有很多其他的作用。而且其构造要比内部类复杂一点,先说说它的作用,作用有二~
    1. 闭包能够保护内部类里面的变量安全,不会被外部访问
    2. 闭包能够维持一个变量一直存活在内存中,不被CG(垃圾回收机制)回收掉
    在构造上,内部类需要提供一个给外部调用它的接口,这样才能在维持住内部类的同时,因为内部类携带了外部类的信息,所以外部类也得以存活。

    二.回调
    回调直接理解就是回头调用,先将相关的方法实现好,但是并不由我来决定什么时候来调用它,而是等到一个时候,程序自己回头调用这个方法,而实现回调机制,这可以说是一种设计模式,而不仅仅是一个语言上的特性。与回调相关的概念还有同步调用,与异步调用,同步调用即单向调用,调用方等待对方执行完成后才返回。异步调用则类似消息机制,等待收到一定的消息后执行某些操作,回调与异步调用有一些共同之处,现在理解的还不是很清楚,先埋下一坑,以后清楚了在补一篇。

    实例:
    接下来就直接上代码分析,让大家补充一些细节上的理解,来清楚整个过程,整个过程相当于我的口述,如有不对的地方,希望大家指出:

    interface Incrementable{
    void increment();
    }

    class Callee1 implements Incrementable{
    private int i = 0;
    public void increment(){
    i++;
    System.out.println(i);
    }
    }

    class MyIncrementable {
    public void increment(){ System.out.println("Other Operarion"); }
    static void f(MyIncrementable mi){ mi.increment(); }
    }

    class Callee2 extends MyIncrementable{
    private int i = 0;
    public void increment(){
    super.increment();
    i++;
    System.out.println(i);
    }
    private class Closure implements Incrementable{
    public void increment(){
    Callee2.this.increment();
    }
    }
    Incrementable getCallbackReference(){
    return new Closure();
    }
    }

    class Caller{
    private Incrementable callbackReference;
    Caller(Incrementable cbn){ callbackReference = cbn; }
    void go(){ callbackReference.increment(); }
    }

    public class Callbacks {
    public static void main(String[] args){
    Callee1 c1 = new Callee1();
    Callee2 c2 = new Callee2();
    MyIncrementable.f(c2);
    Caller caller1 = new Caller(c1);
    Caller caller2 = new Caller(c2.getCallbackReference());
    caller1.go();
    caller1.go();
    caller2.go();
    caller2.go();
    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    这个是java编程思想上很经典的一个例子。输出是这样的:

    Other Operarion
    1
    1
    2
    Other Operarion
    2
    Other Operarion
    3
    1
    2
    3
    4
    5
    6
    7
    8
    希望大家首先自己通读一下代码,然后理解一下程序输出结果为什么是这样的,这样有助于我们去理解之前所说的闭包与回调机制。

    这里我默认大家看完了,我来说一下我的理解:
    首先Callee1是一个简单的实现了接口Incrementable与相关方法,在这里起到一个对比的作用而已。然后实现了一个MyIncrement类同样实现了一个increment()方法但是这个与接口中的increment()没有任何关系,因为这个类自己实现的,并没有实现这个接口,而静态方法f()也只是为了测试一下increment()方法。而Callee2继承自这个类。这里就是重点了。同样写了一个increment()方法,覆盖了父类方法,但是中间还是调用了父类方法。接下里是一个内部类也就是闭包的具体实现了。内部类实现了接口Incrementable并且直接调用外部类的方法作为具体的实现。内部类实现Increment able接口很关键,这样就给外部留下了一个通道,能够接受这个内部类。最后Callee2的后面留下了一个钩子,即getCallbackReference()方法,它返回一个内部类的对象,实现了内部与外部的链接,同时有保证了内部类的安全,因为只有Callee2的对象可以访问与调用这个内部类的方法,而其他的类都无权访问,即使是基类接口对象。而后面的Caller类起到的是一个唤醒作用,通过接受不同的接口对象,实现不同的操作,但还有一个作用是等待接受一个内部类对象,来产生回调。现在大家再回头看一下输出就能够明白了。

    假装你回头看了,在main()方法中,首先是创建对象与声明,然后是调用了一个MyIncrement的静态方法,传入的是一个Callee2对象,此时无法触发回调,所以只是正常的输出,然后,才Caller2的初始化时传入的是一个Closure对象从而产生了回掉。

    以上就是java的闭包与回调机制,结合后面的内容会有更多意想不到的作用~
    ---------------------
    作者:Dev-Y
    来源:CSDN
    原文:https://blog.csdn.net/yuwenhao07/article/details/53607117
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    NumPy笔记:运算符(exp,sqrt,square)
    NumPy笔记:常用操作
    php字符操作
    laravel如何实现批量插入
    php中@符号的作用
    laravel如何实现数据的批量插入
    如何在laravel框架中使用阿里云的oss
    laravle如何设置mysql数据表前缀
    thinkphp视图中如何调用并且向控制器传参数
    thinkphp如何隐藏入口文件index.php
  • 原文地址:https://www.cnblogs.com/handsome1013/p/10747544.html
Copyright © 2011-2022 走看看