乐趣区

[Java菜鸟系列] 协议与回调

[Java 菜鸟系列] 协议与回调
编号:J-003
书接上文,在上一节我们了解了协议的区别和作用。这里来回顾一下。为什么有了抽象类还需要协议呢? 为什么不直接实现某方法,而是非要先签署协议呢?Java8 中在协议中新增的静态方法和默认方法,它们分别有什么用处呢?
上一节讲到,之所以需要先签署协议,再实现某种方法,是因为 Java 是强类型语言,在执行某个方法的时候,必须确认它是存在的。
有了协议的话,这就非常容易了,只要确认他签署了该协议即可 (也就是形参的类型是该协议)。
比喻: 建国初期的时候还没有身份证,那个时候确认身份可麻烦了,要写一封信去籍贯地问问才知道。这就为打击敌特分子的破坏活动,制造了很多障碍。后来我们有了身份证就简单了,只需要看一看就知道是从哪里来的了。
那么,这里我们将介绍一个简单的案例。
协议和回调
在我们之前运行 Java 程序的时候,程序都是按照一定次序运行,然后就自动结束了,但是仔细想一想,就知道,在我们日常生活中,大量的程序都不是这么操作的,很多都是按照我们的键击进行响应的。
闲话: 没办法,Java 就是这么操蛋,写了半天,还没有出一个小框框。JS 程序员更容易找到女朋友的原因就是他们更容易写出框框,轻轻松松就可以装逼了。从这一点来说,如果你学的是 Java,那是悲哀的。
比如说在资源管理器中,按下右键会弹出菜单。这种形式就叫做 ” 事件响应 ”,” 按下右键 ” 就叫做 ” 事件 ”,执行的操作就叫 ” 回调 ”。
比喻: 之前我们的任务都是按照日程表一个一个来执行的,其实那都是实习期老板的花招,你要认为真这么轻松,那你可就是太幼稚。真的进了公司,你就知道,老板让你加班你就得加班啊。

事件响应
在资源管理器中 ” 按下右键 ” 是事件,在公司里 ” 老板叫你 ” 就是事件,对于你的闹钟来说 ” 设置好的时间到了 ” 就是事件;在公司里 ” 老板叫你 ” 的时候,会告诉你具体做什么,比如:” 小张,出去给我买包软中华。”,你定闹钟的时候也会定好 ” 铃声 ” 的种类和音量。
所以,当我们要 ” 事件响应 ” 的时候,我们需要告知 ” 事件出现时 ” 程序应该进行的操作。
有很多其他的编程语言中,我们会直接传入一个字符串参数,来代表函数 / 方法的名字。但是在 Java 中我们更喜欢传入一个对象,因为对象中包含的信息显然更多。
但是这带来了一个问题。
怎么知道该调用对象中的哪个方法呢?
比喻: 公安 A: 队长,这人的身份还没查清楚,他说他是 …. 公安 B: 笨蛋,现在都有身份证了,看看不就知道了!

这里我们拿计时器举例子
计时器好像是闹钟,每隔一段时间就会执行一下你安排的事情。
javax.swing.Timer
我们需要构造一个 Timer 类,构造的过程中,你会发现,构造器需要两个参数。第一个很明显是时间 (dalay),第二个你可以看到,需要 ”ActionListener”(事件监听器)。

问:IDEA 中出现的 @Nullable 是啥意思呢? 答:emmm… 不就是字面意思吗?
问: 字面意思是啥意思啊? 菜鸟之所以为菜鸟,就是因为他不知道的东西,是别人的常识。
答: 在 IDEA 的参数提示中,如果对应的参数是引用类型,那么前面会加上 @Nullable/@NotNull,第一个的意思就是,这个参数允许 Null,第二个意思就是不允许 Null。这种提示可以让我们更好的注意处理 Null 的问题。

也就是说,第二个参数中所需对象必须是扩展自 ActionListener 的,这就相当于公安要查的 ” 身份证 ” 咯。
class Hello implements ActionListener{
// 建立一个 Hello 类 并且签署 “ 事件监听器 ” 的协议, 实现其中的方法
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(“Hello!”);
}
}
办好身份证之后,我们就可以把这个对象传入构造器了。
public static void main(String[] args) {
// 建立一个 Hello 对象, 并且以此对象为参数, 构造一个 timer
Hello a = new Hello();
Timer t = new Timer(1000, a);
// 启动我的定时器
t.start();
}
不过如果你按下了 Run 的话,就会发现。。。
老板: 咦,老资的安排你的事儿咋没做呢? 员工: 可是你说下班了啊。那我只好明天做了。老板:emmm…..

以下内容纯属猜测
程序之所以没有动作,就是因为,如果没有一个对话框之类的东西让程序停止,那么当运行完所有语句的时候,程序就会自动 System.exit(0)。所以如果想让它不停止的话,我们可以这么做。
public static void main(String[] args) {
// 建立一个 Hello 对象, 并且以此对象为参数, 构造一个 timer
Hello a = new Hello();
Timer t = new Timer(1000, a);
// 启动我的定时器
t.start();
// 这里必须挡一下, 否则就自动执行退出了, 哈哈
// 不过如果在 AHK 中, 在 Timer 存在的情况下,程序就不会自动退出
JOptionPane.showMessageDialog(null, “Quit program?”);
System.exit(0);
}

嗯,到这里恭喜你,你已经成功使用了协议和回调。

退出移动版