ホームページ >Java >&#&チュートリアル >Java のコールバック メカニズム (CallBack) についての素晴らしい説明

Java のコールバック メカニズム (CallBack) についての素晴らしい説明

高洛峰
高洛峰オリジナル
2017-01-24 13:25:261433ブラウズ

はじめに

私は最近 Java を学び、コールバック機構 (CallBack) に触れるようになりました。初めてこれに出会ったとき、非常にわかりにくいと感じましたが、インターネットで見つけた関連する説明は、一文で説明されているか、比較的単純で CallBack の定義を提供しているように見えました。もちろん、コールバックを理解した後、インターネットでさまざまな説明を読みましたが、特に問題はありませんでした。ただし、初心者の私にとっては、段階的なプロセスが欠けています。

コールバックとは、双方向の通話モードです。つまり、呼び出したときに相手も呼び出します。これをコールバックといいます。 「電話していただければ、折り返し電話させていただきます。」

わからないですか?それは問題ではありません。最初におそらくコールバックを使用するこのおそらくより古典的な方法を見てみましょう:

クラス A はインターフェイス InA を実装します - バックグラウンド 1

クラス A にはクラス B の参照 b が含まれています - バックグラウンド 2

クラス B InA のパラメーターを持つメソッド test(InA a) があります - 背景 3

A のオブジェクト a は B のメソッドを呼び出し、自身を test(a) に渡します - このステップは、あなたが私を呼ぶのと同じです

そして、 b テスト メソッドで InA メソッドを呼び出すことができます。このステップは、「電話します」と同等です

始める前に、ある場面を想像してください: 幼稚園児は、10 以内の足し算を学んだばかりです。

以下に、コールバックメカニズムについての私の個人的な理解を浅いものから深いものへと順番に説明します。何か間違っている場合は、お気軽に教えてください。

第 1 章 物語の起源

幼稚園の先生が黒板に「1 + 1 = 」という方程式を書き、シャオミンが空欄を埋めました。

Xiao Ming は足し算を 10 以内に学習しているため、この問題を完全に自分で計算できます。プロセスをシミュレートするコードは次のとおりです。

public class Student
 {
  private String name = null;
 
  public Student(String name)
  {
   // TODO Auto-generated constructor stub
   this.name = name;
  }
 
  public void setName(String name)
  {
   this.name = name;
  }
 
  private int calcADD(int a, int b)
  {
   return a + b;
  }
 
  public void fillBlank(int a, int b)
  {
   int result = calcADD(a, b);
   System.out.println(name + "心算:" + a + " + " + b + " = " + result);
  }
 }

Xiao Ming が空白を埋めるとき (fillBalnk)、暗算を直接実行します。 clacADD) 結果は 2 となり、結果を空白のボックスに書き込みます。テスト コードは次のとおりです:

public class Test
 {
  public static void main(String[] args)
  {
  int a = 1;
   int b = 1;
   Student s = new Student("小明");
   s.fillBlank(a, b);
  }
 }

実行結果は次のとおりです:

Xiao Ming の暗算: 1 + 1 = 2

このプロセスは Student クラスのインスタンス オブジェクトによって完全に完了しますのみであり、コールバック メカニズムは含まれません。

第2章 幼稚園の先生のあら探し

授業中、幼稚園の先生は突然思いつき、シャオミンに黒板に「168 + 291 =」と書いて完成させ、事務室に戻りました。

フラワーラブ!なぜ先生たちはシャオミンのことが苦手なのですか?それは明らかにやりすぎです、大丈夫!このとき、シャオミンが上記のように暗算に頼ることができないことは明らかでしたが、混乱していると、クラスの同級生シャオホンが足し算(利得)だけを計算できる電卓を渡しました。 ! ! !シャオミンはたまたま電卓の使い方を知っていたので、電卓を使って結果を計算し、空白を埋めました。

電卓のコードは次のとおりです:

public class Calculator
 {
  public int add(int a, int b)
  {
   return a + b;
  }
 }

Student クラスを変更し、電卓を使用するメソッドを追加します:

public class Student
 {
  private String name = null;
 
  public Student(String name)
  {
   // TODO Auto-generated constructor stub
   this.name = name;
  }
 
  public void setName(String name)
  {
   this.name = name;
  }
 
  @SuppressWarnings("unused")
  private int calcADD(int a, int b)
  {
   return a + b;
  }
 
  private int useCalculator(int a, int b)
  {
   return new Calculator().add(a, b);
  }
 
  public void fillBlank(int a, int b)
  {
   int result = useCalculator(a, b);
   System.out.println(name + "使用计算器:" + a + " + " + b + " = " + result);
  }
 }

テスト コードは次のとおりです:

public class Test
 {
  public static void main(String[] args)
  {
   int a = 168;
   int b = 291;
   Student s = new Student("小明");
   s.fillBlank(a, b);
  }
 }

以下の通り:

Xiao Ming は電卓を使用します: 168 + 291 = 459

コールバック メカニズムはまだこのプロセスに関与していませんが、Xiao Ming の作業の一部は転送され、電卓によって支援されています。

3. 幼稚園の先生が戻ってきて

、シャオ・ミンが3桁の数字の足し算を終えていることに気づきました。先生はシャオ・ミンがとても賢くて、順応性のある才能があると思いました。そこで彼は黒板に「26549 + 16487 = 」と書き、授業に行く前にシャオミンに空欄を埋めるように頼み、それからオフィスに戻りました。

シャオミンは教室の外で友達が楽しんでいるのを見て、悲しくならずにはいられませんでした。遊びに行かないとこの休み場が台無しになってしまうよ! ! ! ! シャオホンが再び手渡した電卓を眺めながら、シャオミンはある計画を思いついた。それはシャオホンにやらせてみることだった。

シャオミンはシャオホンに、お題は「26549 + 16487 = 」であると伝え、結果を記入するための具体的な場所を指定して、楽しく遊びに出かけました。

ここでは、Xiaohong を個別に実装するのではなく、加算のみを実行できるこの電卓と Xiaohong を全体として、結果を計算して空白を埋めることができるスーパー電卓であると考えます。このスーパー電卓に渡す必要があるパラメータは 2 つの加数と埋める位置であり、これらの内容はシャオ ミンに事前に通知する必要があります。つまり、シャオ ミンは自分のメソッドの一部をシャオ ホンに公開したいと考えています。最も簡単な方法は、Xiaohong に引用と 2 つの足し算を一緒に伝えることです。

したがって、スーパー電卓の add メソッドには 2 つのオペランドと Xiao Ming 自身への参照が含まれている必要があります。コードは次のとおりです:

public class SuperCalculator
 {
  public void add(int a, int b, Student xiaoming)
  {
   int result = a + b;
   xiaoming.fillBlank(a, b, result);
  }
 }

Xiao Ming は暗算をしたり、電卓を使用したりする必要はなくなりました。必要なのは、Xiaohong に助けを求める方法だけです。 コードは次のとおりです:

public class Student
 {
  private String name = null;
 
  public Student(String name)
  {
   // TODO Auto-generated constructor stub
   this.name = name;
  }
 
  public void setName(String name)
  {
   this.name = name;
  }
 
  public void callHelp (int a, int b)
  {
   new SuperCalculator().add(a, b, this);
  }
 
  public void fillBlank(int a, int b, int result)
  {
   System.out.println(name + "求助小红计算:" + a + " + " + b + " = " + result);
  }
 }

テスト コードは次のとおりです:

public class Test
 {
  public static void main(String[] args)
  {
   int a = 26549;
   int b = 16487;
   Student s = new Student("小明");
   s.callHelp(a, b);
  }
 }

実行結果は次のとおりです:

Xiao Ming助けを求めます。Xiaohong の計算: 26549 + 16487 = 43036

実行プロセスは次のとおりです。Xiaohong は独自の callHelp メソッドを通じて Xiaohong の add メソッド (new SuperCalculator()) を呼び出し、独自の参照 (this) をパラメーターとして渡します。電話をかけるとき、Hong は電卓を使用して結果を取得した後、Xiao Ming の fillBlank メソッドをコールバックし、結果を黒板の空白スペースに記入しました。

軽い、軽い、軽い!この時点で、Xiao Ming の fillBlank メソッドが正式に登場します。これは、私たちがよくコールバック関数と呼ぶものです。

通过这种方式,可以很明显的看出,对于完成老师的填空题这个任务上,小明已经不需要等待到加法做完且结果填写在黑板上才能去跟小伙伴们撒欢了,填空这个工作由超级计算器小红来做了。回调的优势已经开始体现了。

第4章. 门口的婆婆

幼稚园的门口有一个头发花白的老婆婆,每天风雨无阻在那里摆着地摊卖一些快过期的垃圾食品。由于年纪大了,脑子有些糊涂,经常算不清楚自己挣了多少钱。有一天,她无意间听到了小明跟小伙伴们吹嘘自己如何在小红的帮助下与幼师斗智斗勇。于是,婆婆决定找到小红牌超级计算器来做自己的小帮手,并提供一包卫龙辣条作为报酬。小红经不住诱惑,答应了。

回看一下上一章的代码,我们发现小红牌超级计算器的add方法需要的参数是两个整型变量和一个Student对象,但是老婆婆她不是学生,是个小商贩啊,这里肯定要做修改。这种情况下,我们很自然的会想到继承和多态。如果让小明这个学生和老婆婆这个小商贩从一个父类进行继承,那么我们只需要给小红牌超级计算器传入一个父类的引用就可以啦。

不过,实际使用中,考虑到java的单继承,以及不希望把自身太多东西暴漏给别人,这里使用从接口继承的方式配合内部类来做。

换句话说,小红希望以后继续向班里的小朋友们提供计算服务,同时还能向老婆婆提供算账服务,甚至以后能够拓展其他人的业务,于是她向所有的顾客约定了一个办法,用于统一的处理,也就是自己需要的操作数和做完计算之后应该怎么做。这个统一的方法,小红做成了一个接口,提供给了大家,代码如下:

public interface doJob
 {
  public void fillBlank(int a, int b, int result);
 }

   

因为灵感来自帮小明填空,因此小红保留了初心,把所有业务都当做填空(fillBlank)来做。

同时,小红修改了自己的计算器,使其可以同时处理不同的实现了doJob接口的人,代码如下:

public class SuperCalculator
 {
  public void add(int a, int b, doJob customer)
  {
   int result = a + b;
   customer.fillBlank(a, b, result);
  }
 }

   

小明和老婆婆拿到这个接口之后,只要实现了这个接口,就相当于按照统一的模式告诉小红得到结果之后的处理办法,按照之前说的使用内部类来做,代码如下:
小明的:

public class Student
 {
  private String name = null;
 
  public Student(String name)
  {
   // TODO Auto-generated constructor stub
   this.name = name;
  }
 
  public void setName(String name)
  {
   this.name = name;
  }
 
  public class doHomeWork implements doJob
  {
 
   @Override
   public void fillBlank(int a, int b, int result)
   {
    // TODO Auto-generated method stub
    System.out.println(name + "求助小红计算:" + a + " + " + b + " = " + result);
   }
 
  }
 
  public void callHelp (int a, int b)
  {
   new SuperCalculator().add(a, b, new doHomeWork());
  }
 }

   

老婆婆的:

public class Seller
{
 private String name = null;
 
 public Seller(String name)
 {
  // TODO Auto-generated constructor stub
  this.name = name;
 }
 
 public void setName(String name)
 {
  this.name = name;
 }
 
 public class doHomeWork implements doJob
 {
 
  @Override
  public void fillBlank(int a, int b, int result)
  {
   // TODO Auto-generated method stub
   System.out.println(name + "求助小红算账:" + a + " + " + b + " = " + result + "元");
  }
 
 }
 
 public void callHelp (int a, int b)
 {
  new SuperCalculator().add(a, b, new doHomeWork());
 }
}

   

测试程序如下:

public class Test
{
 public static void main(String[] args)
 {
  int a = 56;
  int b = 31;
  int c = 26497;
  int d = 11256;
  Student s1 = new Student("小明");
  Seller s2 = new Seller("老婆婆");
 
  s1.callHelp(a, b);
  s2.callHelp(c, d);
 }
}

   

运行结果如下:

小明求助小红计算:56 + 31 = 87

老婆婆求助小红算账:26497 + 11256 = 37753元

总结

可以很明显的看到,小红已经把这件事情当做一个事业来做了,看她给接口命的名字doJob就知道了。

有人也许会问,为什么老婆婆摆摊能挣那么多钱? 你的关注点有问题好吗!!这里聊的是回调机制啊!!

我只知道,后来小红的业务不断扩大,终于在幼稚园毕业之前,用挣到的钱买了人生的第一套房子。

以上就是本文对于Java中的回调机制(CallBack) 的有趣详解,希望给大家学习java有所帮助。也谢谢大家对PHP中文网的支持。

更多妙解Java中的回调机制(CallBack)相关文章请关注PHP中文网!

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。