其實它真正的目的僅僅為了定義回調--進一步就是事件驅動。
接口和回調:編程一個常用的模式是回調模式,在這種模式中你可以指定當一個特定時間發生時回調對象上的方法。
注意事項:
匿名類和內部類中的中的this :
有時候,我們會用到一些內部類和匿名類。當在匿名類中用this時,這個this則指的是匿名類或內部類本身。
這時如果我們要使用外部類的方法和變量的話,則應該加上外部類的類名。如下面這個例子:
public class A { int i = 1; public A() { Thread thread = new Thread() { public void run() { for(;;) { A.this.run(); try { sleep(1000); } catch(InterruptedException ie) { } } } }; thread.start(); } public void run() { System.out.println("i = " + i); i++; } public static void main(String[] args) throws Exception { new A(); } }
在上面這個例子中, thread 是一個匿名類對象,在它的定義中,它的 run 函數裡用到了外部類的 run 函數。
這時由於函數同名,直接調用就不行了。這時有兩種辦法,一種就是把外部的 run 函數換一個名字,但這種辦法對於一個開發到中途的應用來說是不可取的
。那麼就可以用這個例子中的辦法用外部類的類名加上 this 引用來說明要調用的是外部類的方法 run。
對於這個例子: this.test(new Inner(){ public void method1(){ System.out.print("1111"); } public void method2(){ System.out.print("22222"); } });
這個時候調用test()方法,那Inner類的method1和method2是什麼時候被調用的?難道也是this對象向他們發消息(比如傳入一個參數)嗎?還是直接顯式的調用??
對於Inner類,除了this這個類,就是this.test(...那句中的this,它能夠調用Inner類的方法,其他地方都不行,然而,這也需要你在類中有個地方保存有對這個內部類實例的引用才可以。再說明一次,內部類是用來在某個時刻調用外面的方法而存在的--這就是回調。
為了說明內部類實例的方法只能在包容類的實例中調用,其他地方無法調用,給個例子如下:
JAVA2實用教程源碼:
/** 一個應用程序,用來演示內部類的使用 */
/** 類Outer */
class Outer{
private static int size;
/** 內部類Inner的聲明 */
public class Inner{
private int size;
/** 方法doStuff() */
public void doStuff(int size){
size++; //存取局部變量
this.size++; //存取其內部類的成員變量
Outer.this.size++; //存取其外部類的成員變量
System.out.println(size+" "+this.size+" "+Outer.this.size);
}
}//內部類Inner結束
/** 類Outer中定義的實例方法testInner()方法 */
public void testInner(){
Inner i=new Inner();
i.doStuff(5);
}
/** main()方法 */
public static void main(String[] a){
Outer o=new Outer();
o.testInner();
}
}//類Outer結束
那麼,如何使用內部類,匿名類實現事件處理呢?
1.事件適配器--EventAdapter
下例中采用了鼠標適配器:
import java.awt.*; import java.awt.event.*; public class MouseClickHandler extends MouseAdaper{ public void mouseClicked(MouseEvent e) //只實現需要的方法 { ……} } java.awt.event包中定義的事件適配器類包括以下幾個: 1.ComponentAdapter( 組件適配器) 2.ContainerAdapter( 容器適配器) 3.FocusAdapter( 焦點適配器) 4.KeyAdapter( 鍵盤適配器) 5.MouseAdapter( 鼠標適配器) 6.MouseMotionAdapter( 鼠標運動適配器) 7.WindowAdapter( 窗口適配器)
2. 用內部類實現事件處理
內部類(inner class)是被定義於另一個類中的類,使用內部類的主要原因是由於:
◇ 一個內部類的對象可訪問外部類的成員方法和變量,包括私有的成員。
◇ 實現事件監聽器時,采用內部類、匿名類編程非常容易實現其功能。
◇ 編寫事件驅動程序,內部類很方便。
因此內部類所能夠應用的地方往往是在AWT的事件處理機制中。
例5.11
import java.awt.* ; import java.awt.event.*; public class InnerClass{ private Frame f; private TextField tf; public InnerClass(){ f=new Frame("Inner classes example"); tf=new TextField(30); } public voidi launchFrame(){ Label label=new Label("Click and drag the mouse"); f.add(label,BorderLayout.NORTH); f.add(tf,BorderLayout.SOUTH); f.addMouseMotionListener(new MyMouseMotionListener());/*參數為內部類對象*/ f.setSize(300,200); f.setVisible(true); } class MyMouseMotionListener extends MouseMotionAdapter{ /*內部類開始*/ public void mouseDragged(MouseEvent e) { String s="Mouse dragging: x="+e.getX()+"Y="+e.getY(); tf.setText(s); } } ; public static void main(String args[]) { InnerClass obj=new InnerClass(); obj.launchFrame(); } }//內部類結束 }
3.匿名類(Anonymous Class)
當一個內部類的類聲名只是在創建此類對象時用了一次,而且要產生的新類需繼承於一個已有的父類或實現一個接口,才能考慮用匿名類,由於匿名類本身無名,因此它也就不存在構造方法,它需要顯示地調用一個無參的父
類的構造方法,並且重寫父類的方法。所謂的匿名就是該類連名字都沒有,只是顯示地調用一個無參的父類的構造方法。
例5.12
import java.awt.* ; import java.awt.event.*; public class AnonymousClass{ private Frame f; private TextField tf; public AnonymousClass(){ f=new Frame("Inner classes example"); tf=new TextField(30); } public void launchFrame(){ Label label=new Label("Click and drag the mouse"); f.add(label,BorderLayout.NORTH); f.add(tf,BorderLayout.SOUTH); f.addMouseMotionListener(new MouseMotionAdapter(){ //匿名類開始 public void mouseDragged(MouseEvent e){ String s="Mouse dragging: x="+e.getX()+"Y="+e.getY(); tf.setText(s); } } ); //匿名類結束 f.setSize(300,200); f.setVisible(true); } public static void main(String args[]) { AnonymousClass obj=new AnonymousClass(); obj.launchFrame(); } }其實仔細分析,例5.11和5.12實現的都是完全一樣的功能,只不過采取的方式不同。5.11中的事件處理類是一個內部類,而5.12的事件處理類是匿名類,可以說從類的關系來說是越來越不清楚,但