Java のコールバック メカニズム (CallBack) についての素晴らしい説明
はじめに
私は最近 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中文网!

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











この記事では、2025年の上位4つのJavaScriptフレームワーク(React、Angular、Vue、Svelte)を分析し、パフォーマンス、スケーラビリティ、将来の見通しを比較します。 強力なコミュニティと生態系のためにすべてが支配的なままですが、彼らの相対的なポップ

この記事では、リモートコードの実行を可能にする重大な欠陥であるSnakeyamlのCVE-2022-1471の脆弱性について説明します。 Snakeyaml 1.33以降のSpring Bootアプリケーションをアップグレードする方法は、このリスクを軽減する方法を詳述し、その依存関係のアップデートを強調しています

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

node.js 20は、V8エンジンの改善、特により速いガベージコレクションとI/Oを介してパフォーマンスを大幅に向上させます。 新機能には、より良いWebセンブリのサポートと洗練されたデバッグツール、開発者の生産性とアプリケーション速度の向上が含まれます。

大規模な分析データセットのオープンテーブル形式であるIcebergは、データの湖のパフォーマンスとスケーラビリティを向上させます。 内部メタデータ管理を通じて、寄木細工/ORCの制限に対処し、効率的なスキーマの進化、タイムトラベル、同時wを可能にします

この記事では、キュウリの手順間でデータを共有する方法、シナリオコンテキスト、グローバル変数、引数の合格、およびデータ構造を比較する方法を調べます。 簡潔なコンテキストの使用、記述など、保守性のためのベストプラクティスを強調しています

この記事では、Lambda式、Streams API、メソッド参照、およびオプションを使用して、機能プログラミングをJavaに統合することを調べます。 それは、簡潔さと不変性を通じてコードの読みやすさと保守性の改善などの利点を強調しています
