在 Java 程式設計中,內部類是一項強大且靈活的機制,而匿名內部類更是事件驅動程式設計的核心工具。本文將系統探討內部類的理論基礎、this 引用的常見陷阱,並透過 AWT 事件處理的實際範例,展示如何優雅地運用內部類與匿名內部類實現回調與事件監聽。
簡單來說,內部類是定義在另一個類內部的類。它存在的核心價值在於:
private 修飾的私有資料。對於包含它的外部類實例而言,內部類實例擁有「特權」。public),除了外部類,其他類都無法直接使用它。歸根結底,內部類的真正目的在於定義回調,進一步支撐事件驅動模型。回調模式允許我們在特定事件發生時,指定呼叫某個物件上的方法。
this 引用在匿名內部類中使用 this 時,它指的是內部類本身。若需呼叫外部類的同名方法或訪問外部類變數,必須使用 外部類名.this 的語法。
public class A {
int i = 1;
public A() {
Thread thread = new Thread() {
public void run() {
for(;;) {
A.this.run(); // 必須加上外部類名 A.this
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(); }
}
此處若直接呼叫 run(),會遞迴呼叫匿名類自身的 run() 導致死循環。透過 A.this.run() 明確指定呼叫外部類方法,避免了重構方法名的麻煩。
class Outer {
private static int size;
public class Inner {
private int size;
public void doStuff(int size) {
size++; // 區域變數
this.size++; // 內部類成員變數
Outer.this.size++; // 外部類成員變數
System.out.println(size + " " + this.size + " " + Outer.this.size);
}
}
public void testInner() {
Inner i = new Inner();
i.doStuff(5);
}
public static void main(String[] a) {
Outer o = new Outer();
o.testInner();
}
}
此例清晰展示了如何區分區域變數、內部類成員、外部類成員三個層級的 size 變數。
Java AWT 事件處理機制大量運用內部類。java.awt.event 包提供了多種適配器類(如 MouseAdapter, WindowAdapter 等),它們實現了對應的監聽器介面並提供空方法體,讓開發者只需覆寫關心的方法。
public class InnerClass {
private Frame f;
private TextField tf;
public InnerClass() {
f = new Frame("Inner classes example");
tf = new TextField(30);
}
public void launchFrame() {
f.addMouseMotionListener(new MyMouseMotionListener()); // 內部類物件
// ... 佈局與顯示代碼省略
}
class MyMouseMotionListener extends MouseMotionAdapter {
public void mouseDragged(MouseEvent e) {
String s = "Mouse dragging: x=" + e.getX() + " Y=" + e.getY();
tf.setText(s);
}
}
}
public class AnonymousClass {
// ... 建構子與欄位相同 ...
public void launchFrame() {
f.addMouseMotionListener(new MouseMotionAdapter() { // 匿名類開始
public void mouseDragged(MouseEvent e) {
String s = "Mouse dragging: x=" + e.getX() + " Y=" + e.getY();
tf.setText(s);
}
}); // 匿名類結束
// ... 佈局與顯示代碼省略
}
}
兩種方式功能完全一致。匿名內部類省去了類名定義,程式碼更緊湊,但類關係較隱晦。熟練掌握兩者對 GUI 開發至關重要。
this 指向自身,訪問外部類需用 OuterClass.this。親自在 IDE 中敲碼實踐,方能深刻體會其設計精妙之處。