這裡我們介紹一種特殊的內部類:局部內部類(Local Inner Classes)。
在前面的例子中,我們可以發現TimerPrinter僅在start方法中建立一個新的對象時出現過一次,其它地方都沒再用到過,這個情況下我們可以把TimerPrinter就定義在start方法中,如下面代碼所示:
public void start(){
class TimerPrinter implements ActionListener{
//private boolean beep;
public void actionPerformed(ActionEvent e){
System.out.println("Bigface,would you be my boy?");
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
TimerPrinter action=new TimerPrinter();
Timer t=new Timer(interval,action);
t.start();
}
注意,局部內部類不需要任何access modifier,否則編譯出錯,它的範圍一般都被限制在它所在的block中。此時,編譯會產生一個名字叫Court$1TimerPrinter的class檔案。局部內部類有如下兩個優點:
1. 它對外面的所有類來說都是隱藏的,即時是它所屬的外部類,僅有它所在的方法知道它;
2. 它不僅可以訪問它所屬外部類中的資料,還可以訪問局部變數,不過局部變數必鬚生命為final類型,看下面的例子:
package cn.edu.hust.cm.test;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Toolkit;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class InnerClassTest {
public InnerClassTest() {
super();
}
public static void main(String[] args) {
Court court=new Court();
court.start(5000,true);
JOptionPane.showMessageDialog(null,"停止麼,CMTobby?");
}
}
class Court{
public void start(int interval,final boolean beep){
class TimerPrinter implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("Cindyelf,are you crazy?");
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
TimerPrinter action=new TimerPrinter();//編譯器會自動更改
Timer t=new Timer(interval,action);
t.start();
}
}
注意,局部內部類所要訪問的局部變數必須聲明為final類型,如上例中紅色粗體部分。那麼局部內部類是如何訪問這個局部變數的呢?我們再對Court$1TimerPrinter反射一下,會得到如下的輸出:
class cn.edu.hust.cm.test.Court$1TimerPrinter
{
cn.edu.hust.cm.test.Court$1TimerPrinter(cn.edu.hust.cm.test.Court, boolean);
public void actionPerformed(java.awt.event.ActionEvent);
final cn.edu.hust.cm.test.Court this$0;
private final boolean val$beep;
}
編譯器又給我們增加了一個域val$beep,同時構造方法增加了一個boolean類型的參數,因此我們猜想如下的實現過程:
TimerPrinter action=new TimerPrinter(this,beep);//編譯器自動增加
然後構造方法中會有:val$beep=beep;這樣就成功的把局部變數的值複製過來了。局部變數必須為final就是為了保證成功的複製值,因為final類型的變數一經賦值就不能再發生變化了。