最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java的回調(diào)機(jī)制

 更新時(shí)間:2022年05月20日 09:26:38   作者:Q-WHai  
最近學(xué)習(xí)java,接觸到了回調(diào)機(jī)制(CallBack)。初識(shí)時(shí)感覺(jué)比較混亂,而且在網(wǎng)上搜索到的相關(guān)的講解,本文介紹了Java的回調(diào)機(jī)制,有興趣的同學(xué)可以了解一下

模塊之間總是存在這一定的接口,從調(diào)用方式上看,可以分為三類(lèi):同步調(diào)用、回調(diào)和異步調(diào)用。下面著重詳解回調(diào)機(jī)制。

1. 概述

Java 中的回調(diào)機(jī)制是一個(gè)比較常見(jiàn)的機(jī)制,只是有可能在你的程序中使用得比較少,在一些大型的框架中回調(diào)機(jī)制隨處可見(jiàn)。本文就通過(guò)一些具體的實(shí)例,慢慢走近 Java 的回調(diào)機(jī)制。

2.回調(diào)

所謂回調(diào):就是A類(lèi)中調(diào)用B類(lèi)中的某個(gè)方法C,然后B類(lèi)中反過(guò)來(lái)調(diào)用A類(lèi)中的方法D,D這個(gè)方法就叫回調(diào)方法。實(shí)際在使用的時(shí)候,也會(huì)有不同的回調(diào)形式,比如下面的這幾種。

2.1 同步回調(diào)

這里我假設(shè)這樣的一種情況。

A 公司的總監(jiān) B 跟他的下屬(項(xiàng)目經(jīng)理 C)說(shuō)要做一個(gè)調(diào)研,不過(guò)不用 C 自己親力親為。可以讓經(jīng)理 C 去安排他下面的程序員 D 去完成。經(jīng)理 C 找到了程序員 D,并告訴他,現(xiàn)在要完成一個(gè)調(diào)研任務(wù)。并且把調(diào)研的結(jié)果告訴經(jīng)理 C。如果有問(wèn)題,還是要繼續(xù)的。 因?yàn)檫@里是 C 讓 D 去做一件事情,之后 D 還是要將結(jié)果與 C 進(jìn)行溝通。這樣就是回調(diào)的模型了。下面是一般回調(diào)的類(lèi)圖:

首先我們要有一個(gè)回調(diào)的接口 CallbackInterface

CallbackInterface.java

public interface CallbackInterface {
  public boolean check(int result);
}

背景里,程序員 D 是要將結(jié)果與項(xiàng)目經(jīng)理 C 進(jìn)行溝通的,所以這里項(xiàng)目經(jīng)理需要實(shí)現(xiàn)上面的回調(diào)接口:

Manager.java

public class Manager implements CallbackInterface {

  private Programmer programmer = null;

  public Manager(Programmer _programmer) {
    this.programmer = _programmer;
  }

  /**
   * 用于 Boss 下達(dá)的委托
   */
  public void entrust() {
    arrange();
  }

  // 進(jìn)行安排下屬進(jìn)行 study 工作
  private void arrange() {
    System.out.println("Manager 正在為 Programmer 安排工作");
    programmer.study(Manager.this);
    System.out.println("為 Programmer 安排工作已經(jīng)完成,Manager 做其他的事情去了。");
  }

  @Override
  public boolean check(int result) {
    if (result == 5) {
      return true;
    }
    return false;
  }

}

對(duì)于程序員 D 來(lái)說(shuō)他需要持有一個(gè)經(jīng)理 C 的引用,以便與他溝通。不過(guò),這里是總監(jiān) B 讓 經(jīng)理 C 去安排的任務(wù)。也就是說(shuō)這里也可以讓其他的經(jīng)理,比如說(shuō)經(jīng)理 B1, B2等等。因?yàn)榻?jīng)理都實(shí)現(xiàn)了回調(diào)的接口,所以這里就可以直接讓程序員 D 持有這個(gè)接口就可以了。如下:

Programmer.java

public class Programmer {

  public void study(CallbackInterface callback) {
    int result = 0;
    do {
      result++;
      System.out.println("第 " + result + " 次研究的結(jié)果");
    } while (!callback.check(result));

    System.out.println("調(diào)研任務(wù)結(jié)束");
  }
}

對(duì)于總監(jiān)來(lái)說(shuō)就更簡(jiǎn)單明了了,因?yàn)檫@相當(dāng)于一個(gè) Client 測(cè)試:

Boss.java

public class Boss {

  public static void main(String[] args) {
    Manager manager = new Manager(new Programmer());
    manager.entrust();
  }
}

運(yùn)行結(jié)果:

Manager 正在為 Programmer 安排工作
第 1 次研究的結(jié)果
第 2 次研究的結(jié)果
第 3 次研究的結(jié)果
第 4 次研究的結(jié)果
第 5 次研究的結(jié)果
調(diào)研任務(wù)結(jié)束
為 Programmer 安排工作已經(jīng)完成,Manager 做其他的事情去了。

2.2 異步回調(diào)

還是上面的例子,你的項(xiàng)目經(jīng)理不可能要一直等你調(diào)研的結(jié)果。而是把這個(gè)任務(wù)交給你之后,他就不管了,他做他的,你做你的。所以,這里需要對(duì)回調(diào)的函數(shù)進(jìn)行異步處理。
所以,這里我們需要修改 Programmer 類(lèi)的代碼,修改如下:

Programmer.java

public class Programmer {

  public Programmer() {
  }

  public void study(CallbackInterface callback) {
    new StudyThread(callback).start();
  }

  // --------------------------- Programmer 正在做的工作 ---------------------------

  class StudyThread extends Thread {

    CallbackInterface callback = null;

    public StudyThread(CallbackInterface _callback) {
      callback = _callback;
    }

    @Override
    public void run() {
      int result = 0;
      do {
        result++;
        System.out.println("第 " + result + " 次研究的結(jié)果");
      } while (!callback.check(result));

      System.out.println("調(diào)研任務(wù)結(jié)束");
    }
  }
}

運(yùn)行結(jié)果:

Manager 正在為 Programmer 安排工作
為 Programmer 安排工作已經(jīng)完成,Manager 做其他的事情去了。
第 1 次研究的結(jié)果
第 2 次研究的結(jié)果
第 3 次研究的結(jié)果
第 4 次研究的結(jié)果
第 5 次研究的結(jié)果
調(diào)研任務(wù)結(jié)束

2.3 閉包與回調(diào)

閉包(closure)是一個(gè)可調(diào)用的對(duì)象,它記錄了一些信息,這些信息來(lái)自于創(chuàng)建它的作用域。

2.3.1 普通調(diào)用

首先,我們可以看看在正常情況下的調(diào)用是怎么進(jìn)行的。
Incrementable.java

interface Incrementable {
  void increment();
}

這是一個(gè)普通的接口(在普通調(diào)用里只是普通接口,在回調(diào)中就是回調(diào)接口,這一點(diǎn)應(yīng)該很好理解吧)。

Callee1.java

class Callee1 implements Incrementable {

  private int i = 0;

  @Override
  public void increment() {
    i++;
    System.out.println(i);
  }

}

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();
    callee1.increment();
  }
}

Callbacks 是一個(gè)測(cè)試客戶(hù)端類(lèi),沒(méi)啥好說(shuō)的,直接看上面的代碼。

2.3.2 回調(diào)初試

上面的普通調(diào)用也沒(méi)啥好說(shuō)的,因?yàn)檫@對(duì)于一個(gè)正常的 Java 程序員來(lái)說(shuō)都應(yīng)該是想都不用想就可以搞定的事情。

現(xiàn)在如果要構(gòu)成回調(diào),那么對(duì)于程序的結(jié)構(gòu)或是邏輯的思維上都不可能只有一個(gè)被調(diào)用者(被回調(diào)的對(duì)象 Callee1),還需要一個(gè)調(diào)用者對(duì)象。調(diào)用者可以像下面這樣來(lái)編寫(xiě):

Caller.java

class Caller {

  private Incrementable callbackReference;

  public Caller(Incrementable _callbackReference) {
    callbackReference = _callbackReference;
  }

  void go() {
    callbackReference.increment();
  }
}

這里 Caller 持有一個(gè)回調(diào)接口的引用 callbackReference,就像在上面說(shuō)到的程序員需要持有一個(gè)項(xiàng)目經(jīng)理的引用,這樣就可以通過(guò)這個(gè)引用來(lái)與項(xiàng)目經(jīng)理溝通。這里的 callbackReference 也正是起到了這個(gè)作用。

現(xiàn)在我們來(lái)看看測(cè)試類(lèi)的編寫(xiě):

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();    
    Caller caller1 = new Caller(callee1);
    caller1.go();
  }
}

對(duì)于到目前為止的程序代碼,完全可以對(duì)比上面項(xiàng)目經(jīng)理安排程序員調(diào)研技術(shù)難題的代碼。有異曲同工之妙。

2.3.3 閉包回調(diào)

相比于正常的回調(diào),閉包回調(diào)的核心自然是在于閉包,也就是對(duì)作用域的控制。
現(xiàn)在假設(shè)有一個(gè)用戶(hù)(其他程序員)自定義了一個(gè) MyInCrement 類(lèi),同時(shí)包含了一個(gè) increment 的方法。如下:

class MyInCrement {

  public void increment() {
    System.out.println("MyCrement.increment");
  }

  static void f(MyInCrement increment) {
    increment.increment();
  }
}

另外有一個(gè)類(lèi) Callee2 繼承自上面這個(gè)類(lèi):

class Callee2 extends MyInCrement {

  private int i = 0;

  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
}

顯而易見(jiàn)這里如果要調(diào)用 increment() 方法,就變成了一般的函數(shù)調(diào)用了。所以這里我們需要修改上面的 Callee2 類(lèi),修改的目標(biāo)就是讓 Callee2 類(lèi)可以兼容 MyInCrement 類(lèi)的 increment() 方法和 Incrementable 的 increment() 方法。修改后:

class Callee2 extends MyInCrement {

  private int i = 0;

  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }

  private class Closure implements Incrementable {

    @Override
    public void increment() {
      Callee2.this.increment();
    }
  }

  Incrementable getCallbackReference() {
    return new Closure();
  }
}

注意,這里的 Closure 類(lèi)是一個(gè)私有的類(lèi),這是一個(gè)閉包的要素。因?yàn)?Closure 類(lèi)是私有的,那么就要有一個(gè)對(duì)外開(kāi)放的接口,用來(lái)對(duì) Closure 對(duì)象的操作,這里就是上面的 getCallbackReference() 方法。 Caller 類(lèi)則沒(méi)有改變。
對(duì)于測(cè)試客戶(hù)端就直接看代碼吧:

public class Callbacks {
  public static void main(String[] args) {    
    Callee2 callee2 = new Callee2();
    Caller caller2 = new Caller(callee2.getCallbackReference());
    caller2.go();
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot關(guān)于List集合的校驗(yàn)方式

    SpringBoot關(guān)于List集合的校驗(yàn)方式

    這篇文章主要介紹了SpringBoot關(guān)于List集合的校驗(yàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • SpringBoot結(jié)合Quartz實(shí)現(xiàn)數(shù)據(jù)庫(kù)存儲(chǔ)

    SpringBoot結(jié)合Quartz實(shí)現(xiàn)數(shù)據(jù)庫(kù)存儲(chǔ)

    本文主要介紹了SpringBoot+Quartz+數(shù)據(jù)庫(kù)存儲(chǔ),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • springboot使用dubbo和zookeeper代碼實(shí)例

    springboot使用dubbo和zookeeper代碼實(shí)例

    這篇文章主要介紹了springboot使用dubbo和zookeeper代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java Servlet簡(jiǎn)單實(shí)例分享(文件上傳下載demo)

    Java Servlet簡(jiǎn)單實(shí)例分享(文件上傳下載demo)

    下面小編就為大家?guī)?lái)一篇Java Servlet簡(jiǎn)單實(shí)例分享(文件上傳下載demo)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • Java實(shí)戰(zhàn)之圖書(shū)管理系統(tǒng)的實(shí)現(xiàn)

    Java實(shí)戰(zhàn)之圖書(shū)管理系統(tǒng)的實(shí)現(xiàn)

    這篇文章主要介紹了如何利用Java語(yǔ)言編寫(xiě)一個(gè)圖書(shū)管理系統(tǒng),文中采用的技術(shù)有Springboot、SpringMVC、MyBatis、ThymeLeaf 等,需要的可以參考一下
    2022-03-03
  • java的Builder原理和實(shí)現(xiàn)詳解

    java的Builder原理和實(shí)現(xiàn)詳解

    大家好,本篇文章主要講的是java的Builder原理和實(shí)現(xiàn)詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下,方便下次瀏覽
    2021-12-12
  • java實(shí)現(xiàn)打印正三角的方法

    java實(shí)現(xiàn)打印正三角的方法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)打印正三角的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 深入了解Java中Cookie和Session的區(qū)別

    深入了解Java中Cookie和Session的區(qū)別

    會(huì)話(huà)跟蹤是Web程序中常用的技術(shù),用來(lái)跟蹤用戶(hù)的整個(gè)會(huì)話(huà),常用的會(huì)話(huà)跟蹤技術(shù)是Cookie與Session,本文就詳細(xì)的介紹一下Java中Cookie和Session的區(qū)別,感興趣的可以了解一下
    2023-06-06
  • Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除功能

    Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除功能

    這篇文章主要介紹了Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Spring Boot配置AOP打印日志的全過(guò)程

    Spring Boot配置AOP打印日志的全過(guò)程

    這篇文章主要給大家介紹了關(guān)于Spring Boot配置AOP打印日志的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08

最新評(píng)論

工布江达县| 宁夏| 靖宇县| 安国市| 水富县| 芮城县| 伊宁市| 徐水县| 金寨县| 晋宁县| 华亭县| 舒城县| 庆安县| 桃源县| 巴东县| 施甸县| 遂溪县| 东乡族自治县| 龙游县| 太康县| 明光市| 卓资县| 凌海市| 乡城县| 新干县| 建平县| 田林县| 榆树市| 尖扎县| 义马市| 新闻| 博白县| 沁水县| 北海市| 宁都县| 朝阳区| 陇川县| 那坡县| 福贡县| 苍南县| 安顺市|