0%

java回调机制

在安卓与源码中,很多地方用到了回调机制,最近学习java,接触到了回调机制(CallBack),理解它很有必要。
循序渐进来理解java的回调机制。

一、普通的功能和方法调用

我们用一个加法的实现功能来引出并理解回调。模拟一个低年级的小朋友去做老师布置的加法题目,简单的加法题目。比如,这里先是1+1。小明很容易就算出答案,我们也写出最简单的代码。

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
 1 public class Student
2 {
3 private String name = null;
4
5 public Student(String name)
6 {
7 // TODO Auto-generated constructor stub
8 this.name = name;
9 }
10
11 public void setName(String name)
12 {
13 this.name = name;
14 }
15
16 private int calcADD(int a, int b)
17 {
18 return a + b;
19 }
20
21 public void fillBlank(int a, int b)
22 {
23 int result = calcADD(a, b);
24 System.out.println(name + "心算:" + a + " + " + b + " = " + result);
25 }
26 }

客户端代码:

1
2
3
4
5
6
7
8
9
10
 1 public class Test
2 {
3 public static void main(String[] args)
4 {
5 int a = 1;
6 int b = 1;
7 Student s = new Student("小明");
8 s.fillBlank(a, b);
9 }
10 }

运行结果:

1
小明心算:1 + 1 = 2

二、改进后的代码

假设老师布置的是189 + 231呢?小明怎么办呢?我们假设小明没有学过三位数的加法,他最多学到来能位数的,这时小明可能要借助计算器来帮助他算。如果把计算的功能单独抽出来,并修改Student类,如下:
新增一个计算器类:

1
2
3
4
5
6
7
1 public class Calculator
2 {
3 public int add(int a, int b)
4 {
5 return a + b;
6 }
7 }

修改后的Student类:

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

1 public class Student
2 {
3 private String name = null;
4
5 public Student(String name)
6 {
7 // TODO Auto-generated constructor stub
8 this.name = name;
9 }
10
11 public void setName(String name)
12 {
13 this.name = name;
14 }
15
16 @SuppressWarnings("unused")
17 private int calcADD(int a, int b)
18 {
19 return a + b;
20 }
21
22 private int useCalculator(int a, int b)
23 {
24 return new Calculator().add(a, b);
25 }
26
27 public void fillBlank(int a, int b)
28 {
29 int result = useCalculator(a, b);
30 System.out.println(name + "使用计算器:" + a + " + " + b + " = " + result);
31 }
32 }

如上所示。客户端代码如下:

1
2
3
4
5
6
7
8
9
10
 1 public class Test
2 {
3 public static void main(String[] args)
4 {
5 int a = 189;
6 int b = 231;
7 Student s = new Student("小明");
8 s.fillBlank(a, b);
9 }
10 }

运行结果:

1
小明使用计算器:189 + 231 = 410

三、继续引出问题(老师继续出更加超纲的题)

老师觉得小名很聪明,于是加大了题目的难度,如果老师继续出的题是26549 + 16487 呢?小明应该怎么办呢?
小名当然可以继续用计算器算,但是不需要每次都自己算,我们可以改进一下代码:
定义一个超级计算器类,超级计算器的add方法应该包含两个操作数和小明自身的引用:

1
2
3
4
5
6
7
8
 public class SuperCalculator
2 {
3 public void add(int a, int b, Student xiaoming)
4 {
5 int result = a + b;
6 xiaoming.fillBlank(a, b, result);
7 }
8 }

修改后Student代码:

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
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);
}
}

客户端代码:

1
2
3
4
5
6
7
8
9
10
public class Test
{
public static void main(String[] args)
{
int a = 26549;
int b = 16487;
Student s = new Student("小明");
s.callHelp(a, b);
}
}

运行结果:

1
小明求助小红计算:26549 + 16487 = 43036

执行流程为:小明通过自身的callHelp方法调用了小红(new SuperCalculator())的add方法,在调用的时候将自身的引用(this)当做参数一并传入,小红在使用计算器得出结果之后,回调了小明的fillBlank方法,将结果填在了黑板上的空格里。
灯灯灯!到这里,回调功能就正式登场了,小明的fillBlank方法就是我们常说的回调函数
通过这种方式,可以很明显的看出,对于完成老师的填空题这个任务上,小明已经不需要等待到加法做完且结果填写在黑板上才能去跟小伙伴们撒欢了,填空这个工作由超级计算器小红来做了。回调的优势已经开始体现了。

四、理解回调

如果不仅仅小明需要这个计算的功能,一个小商贩(如果一位老奶奶平时卖东西,但是她不太会算数)也需要呢?
我们定义一个接口,如下:

1
2
3
4
public interface doJob
{
public void fillBlank(int a, int b, int result);
}

修改后的超级计算器

1
2
3
4
5
6
7
8
public class SuperCalculator
{
public void add(int a, int b, doJob customer)
{
int result = a + b;
customer.fillBlank(a, b, result);
}
}

修改后的Student类代码(小明的代码):

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
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());
}
}

小商贩的代码:

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
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());
}
}

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
}
}

运行结果:

1
2
小明求助小红计算:56 + 31 = 87
老婆婆求助小红算账:26497 + 11256 = 37753元

以上就是回调的整个过程,也就是从计算加法引申出来。