머리말
최근에 Java를 배우며 콜백 메커니즘(CallBack)을 접하게 되었습니다. 처음 만났을 때 꽤 헷갈린다고 느꼈고, 인터넷에서 찾은 관련 설명이 한 문장으로 설명되어 있거나, 비교적 단순해서 콜백에 대한 정의를 내리는 것 같았습니다. 물론 콜백을 이해한 후 인터넷에서 여러 가지 설명을 찾아 읽어봤는데 정말 문제가 없었습니다. 그러나 초보자인 저에게는 단계별 프로세스가 누락되었습니다.
콜백은 양방향 통화 모드입니다. 즉, 호출되면 수신자도 상대방에게 전화를 겁니다. "전화주시면 다시 전화드리겠습니다."
이해가 안 되시나요? 상관없습니다. 콜백을 사용하는 보다 고전적인 방법을 살펴보겠습니다.
클래스 A는 인터페이스 InA를 구현합니다. - 배경 1
클래스 A에 포함되어 있습니다. a 클래스 B 참조 b - 배경 2
클래스 B에는 InA 매개변수를 갖는 test(InA a) 메소드가 있습니다. - 배경 3
A의 객체 a가 B의 The를 호출합니다. 메소드는 자체적으로 전달됩니다. 테스트(a) - 이 단계는 you call me
와 동일하며 b는 테스트 메소드에서 InA의 메소드를 호출할 수 있습니다. - 이 단계는 i call you back
시작하기 전에 장면을 상상해 보세요. 유치원 아이들이 방금 10 이내의 덧셈을 배웠습니다.
아래에서는 콜백 메커니즘에 대한 개인적인 이해를 얕은 것부터 깊은 것 순으로 설명하겠습니다. 잘못된 점이 있으면 언제든지 알려주시기 바랍니다.
1장. 이야기의 유래
유치원 선생님이 칠판에 방정식 "1 + 1 = "을 썼고, 샤오밍이 빈칸을 채웠습니다.
10 이내의 덧셈을 배웠기 때문에 Xiao Ming은 이 문제를 혼자서 완전히 계산할 수 있습니다. 이 과정을 시뮬레이션하는 코드는 다음과 같습니다.
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); } }
실행 결과는 다음과 같습니다.
샤오밍의 암산: 1 + 1 = 2
이 프로세스는 Student 클래스의 인스턴스 객체만으로 완전히 완료되며 콜백 메커니즘을 포함하지 않습니다.
2장. 유치원 선생님의 고민 찾기
쉬는 시간에 유치원 선생님이 문득 생각이 나서 샤오밍이 완성하라고 칠판에 “168 + 291 =”이라고 썼고, 그런 다음 사무실로 돌아 왔습니다.
꽃 문지름! 왜 모든 선생님들은 샤오밍 때문에 어려움을 겪나요? 분명히 최고 수준입니다. 알았습니다! 이때 Xiao Ming은 더 이상 위와 같은 암산에 의존할 수 없음이 분명했습니다. 그가 혼란스러워했을 때 같은 반 친구인 Xiao Hong은 덧셈만 계산할 수 있는 계산기를 건네주었습니다(수익자)! ! ! ! Xiao Ming은 우연히 계산기 사용법을 알고 있었기 때문에 계산기를 사용하여 결과를 계산하고 빈칸을 채웠습니다.
계산기 코드는
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. 유치원 선생님이 돌아와서
Xiao Ming이 세 자리 덧셈을 완료한 것을 발견했습니다. 선생님은 Xiao Ming이 매우 똑똑하고 유연한 재능을 가지고 있다고 생각했습니다. 그래서 그는 칠판에 "26549 + 16487 = "이라고 쓰고 수업에 가기 전에 Xiao Ming에게 빈칸을 채우도록 요청한 후 사무실로 돌아 왔습니다.
샤오밍은 교실 밖에서 친구들이 즐겁게 노는 모습을 보며 안타까움을 금할 수 없었습니다. 우리가 놀러 나가지 않으면 이 쉬는 시간이 망가질 거예요! ! ! ! 샤오홍이 다시 건네준 계산기를 보고 샤오밍은 계획을 세웠다. 샤오홍이 그녀에게 계산기를 하게 하는 것이다.
샤오밍은 샤오홍에게 주제가 "26549 + 16487 = "이라고 말했고, 결과를 채울 구체적인 위치를 지적한 뒤 즐겁게 놀러 나갔다.
여기서는 샤오홍을 따로 구현하는 것이 아니라 덧셈과 샤오홍만 전체적으로 수행할 수 있는 계산기, 결과를 계산하고 빈칸을 채울 수 있는 슈퍼 계산기라고 생각합니다. 이 슈퍼 계산기에 전달해야 하는 매개변수는 두 개의 가수와 채워야 할 위치이며, 이러한 내용은 Xiao Ming에게 미리 알려야 합니다. 이는 Xiao Ming이 자신의 방법 중 일부를 Xiao Hong에게 공개하고 싶어 함을 의미합니다. 가장 간단한 방법은 Xiaohong에게 인용문과 두 덧셈을 함께 알려주는 것입니다.
따라서 슈퍼 계산기의 add 메소드에는 두 개의 피연산자와 Xiao Ming 자신에 대한 참조가 포함되어야 합니다.
public class SuperCalculator { public void add(int a, int b, Student xiaoming) { int result = a + b; xiaoming.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 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이 Xiao Hong에게 도움을 요청했습니다. 계산: 26549 + 16487 = 43036
실행 프로세스는 다음과 같습니다. Xiao Ming은 자신의 callHelp 메소드를 통해 Xiao Hong의 add 메소드(새로운 SuperCalculator())를 호출하고 자신의 참조(이것은 )를 호출할 때 매개변수로 Xiaohong은 계산기를 사용하여 결과를 얻은 후 Xiaoming의 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中文网!