Java SE 是什么,包括哪些内容(二十)?
本文内容参考自Java8标准
再次感谢Java编程思想对本文的启发!
接下来在将要介绍的控制框架中,可以看到更多使用内部类的具体例子。
应用程序框架就是被设计用以解决某一类特定问题的一个类或一组类。要运用某个应用程序框架,通常是继承一个或多个类,并覆盖某些方法,在覆盖后的方法中,编写代码定制应用程序框架提供的通用解决方案,以解决你的问题。
控制框架是一类特殊的应用程序框架,它用来解决响应时间的需求。主要用来响应事件的系统被称作事件驱动系统(根据实际发生的事件作出响应,被事件驱动执行)。应用程序设计中常见的问题之一的图形用户接口(GUI),它几乎完全是事件驱动系统(Java Swing库就是一个控制框架,它优雅地解决了GUI的问题,并使用了大量的内部类)。
要理解内部类是如何允许简单的创建过程以及如何使用控制框架的,可以考虑这样一个控制框架:它的工作就是在事件"就绪"的时候执行事件。虽然"就绪"可以指任何事情,但在本例中是指基于事件触发的事件。
接下来的问题就是:你要控制什么?控制框架并不包含任何具体的信息,那些信息是在实现算法时,通过继承来提供的(也就是说,具体的实现是在继承了框架的某个类之后由你提供)。
下面给出一个含有具体实现的例子:
首先,接口描述了要控制的事件,因为默认的行为是基于时间去执行控制,所以使用抽象类代替实际的接口(抽象类能含有控制时间的代码,接口不能)。
代码示例:
// 基于时间控制
//抽象类Event
public abstract class Event{
//long类型的类变量eventTime,代表事件的时间
private long eventTime;
//protected final long类型的类变量delayTime,代表延时
protected final long delayTime;
//构造方法,带一个long类型的形式参数delayTime
public Event(long delayTime){
//初始化类变量
this.delayTime = delayTime;
//执行方法start()
start();
}
//方法start()
public void start(){
//将System.nanoTime() + delayTime的值赋给类变量eventTime
eventTime = System.nanoTime() + delayTime;
}
//方法ready(),返回类型为boolean
public boolean ready(){
//返回System.nanoTime()的值是否大于eventTime的值
return System.nanoTime() >= eventTime;
}
//抽象方法action(),带继承类实现
public abstract void action();
}
当希望运行Event并随后调用方法start()时,类Event的构造方法就会捕获时间(执行System.nanoTime(),它表示的是从对象创建的时刻开始的时间)。
此时间是这样的来的:方法start()获取当前时间,然后加上一个延迟时间,这样生成触发事件的时间。start()是一个独立的方法,它之所以没有包含在构造器内部(就是整个方法体没有直接写进类Event的构造方法里面),是因为这样就可以在事件运行以后重新启动计时器,这样就能够重复使用Event对象。比如,如果你想要简单地重复一个事件,只需简单地在实现方法action()的时候再调用方法start()。
方法ready()告诉你何时可以运行方法action(),当然,你还可以在导出类中覆盖ready()方法,使得Event能够基于时间以外的其它因素而触发。
下面的示例代码中包含了一个用来管理并触发事件的实际控制框架。Event对象被保存在List< Event >类型(Event列表)的容器对象中(容器在后面的博文中会作详细介绍,目前你只需要知道add()方法用来将一个Object添加到List的尾端,size()方法用来得到List中元素的个数,foreach语法用来连续获得List中的Event对象,remove()方法用来从List中移除指定的Event对象)。
代码示例:
// 实际的控制框架
//类Controller,代表一个控制器
public class Controller{
//一个List容器,装所有的Event,这里使用了泛型,后面博文中会提,保证了类型的安全
private List<Event> eventList = new ArrayList<Event>();
//方法addEvent(Event c),带一个Event类型的形式参数c
public void addEvent(Event c){
//将这个c添加到List容器中
eventList.add(c);
}
//执行的方法run()
public void run(){
//while循环,条件是容器内的Event对象数量大于0(eventList.size()>0)
while(eventList.size()>0){
//如果容器内的Event对象数量大于0,则复制一份List容器
//(重新创建了一个Arraylist对象:new ArrayList<Event>(eventList))
//复制是为了在同一个容器内选择元素的时候不修改它
for(Event e : new ArrayList<Event>(eventList)){
//如果e准备就绪