作为一个小白,不管看多么简单的程序都经常会产生这样或那样的困惑。而这些困惑产生的原因也大都是自己学得不好,基础不扎实造成的。可偏偏,自己默默地百度到了答案,下次见还是不会,所以还是写下来吧,不为了别人看了点个赞,只是为了留下个深刻点的印象。
问题还是要从一块代码开始:
这是一块比较简单的处理事件的代码,当时看这个产生的疑惑主要是,new了一个SeclectonListener 类,但是里面定义的两个函数除了名称不一样,其他地方都是一毛一样的,用什么区分不同的监听事件?所以我去找了SeclectionListener的源码:
public interface SelectionListener extends SWTEventListener {
/**
* Sent when selection occurs in the control.
* <p>
* For example, selection occurs in a List when the user selects
* an item or items with the keyboard or mouse. On some platforms,
* the event occurs when a mouse button or key is pressed. On others,
* it happens when the mouse or key is released. The exact key or
* mouse gesture that causes this event is platform specific.
* </p>
*
* @param e an event containing information about the selection
*/
public void widgetSelected(SelectionEvent e);
/**
* Sent when default selection occurs in the control.
* <p>
* For example, on some platforms default selection occurs in a List
* when the user double-clicks an item or types return in a Text.
* On some platforms, the event occurs when a mouse button or key is
* pressed. On others, it happens when the mouse or key is released.
* The exact key or mouse gesture that causes this event is platform
* specific.
* </p>
*
* @param e an event containing information about the default selection
*/
public void widgetDefaultSelected(SelectionEvent e);
}
注释里写的很明白了,一个widgetSelected是 监听单击的事件,一个widgetDefaultSelected是监听双击的事件。至于说具体是怎么实现的,这里没有解释,应该是在底层实现的,默认不展示吧。
这里的new SelectionListener{} 又是个什么东西,为什么可以将自己本身定义的方法进行重写呢?这就涉及到了一个比较重要的知识点:匿名内部类。了解匿名内部类要知道3点:
1, 匿名内部类就是不能有名字的内部类,不能被引用,只能在应用的时候用new 来声明。,
2, 使用匿名内部类的一个条件是:这个类必须是一个抽象类或者接口。
3, 匿名内部类的作用:简化代码的书写。
下面通过例子来解释第3点 :
此处例子参考 点击打开链接
例1:不使用匿名内部类来实现抽象方法
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
运行结果:eat something
简单分析一下这个程序:为了实现eat()方法,新建一个Child类继承Person类,然后实现一个Child 实例。这里比较有意思的一点是Person p = new Child() 这句是将Child 向上转型,为的就是调用重新定义的eat()方法。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦。。这时就引入了匿名内部类。
例2:用匿名内部类来实现抽象方法
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
运行结果:eat something
这里运用匿名内部类直接将Person中的方法直接在 大括号中实现了,这样就省略了一个类的书写。 匿名内部类还能运用到接口中去。
例3:在接口上使用匿名内部类
interface Person {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
运行结果:eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
例4:Thread类的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
运行结果:1 2 3 4 5
例5:Runnable 接口的匿名内部类的实现
public class Demo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
Thread t = new Thread(r);
t.start();
}
}
运行结果:1 2 3 4 5
回到开篇的那个小例子,SeclectionListener 是一个接口,在这里运用匿名内部类实际上的执行流程还是一个定义一个非抽象类实现这个SeclectionListener 接口的。实现了这个接口,那么就必须实现接口中的那两个方法,但如果接口中有N 个方法,但是只需要用其中的一两个怎么办呢?这样就引入了适配器的概念。(待续)