java核心技術卷I-內部類

內部類

內部類(inner class) 是定義在另一個類中的類。使用原因如下:
1.內部類方法可以訪問該類定義所在的作用域中的數據, 包括私有的數據。
2.內部類可以對同一個包中的其他類隱藏起來。
3.當想要定義一個回調函數且不想編寫大量代碼時,使用匿名 (anonymous) 內部類比較便捷。

使用內部類訪問對象狀態

public class TalkingClock
{
	private int interval:
	private boolean beep;
	public TalkingClock(int interval, boolean beep) { . . . }
	public void start() { • . . }
    public class TimePrinter implements ActionListener
	// an inner class
	{
    	public void actionPerformed(ActionEvent event) {
			System.out.println("At the tone, the time is " + new Oate();)
			if (beep) Toolkit.getDefaultToolkit().beep(); 
		}
	} 
}

內部類既可以訪問自身的數據域,也可以訪問創建它的外圍類對象的數據域。爲了能夠運行這個程序, 內部類的對象總有一個隱式引用, 它指向了創建它的外部類對象。
在這裏插入圖片描述
TimePrinter 類聲明爲私有的。這樣一來, 只有 TalkingClock 的方法才能夠構造TimePrinter 對象。只有內部類可以是私有類,而常規類只可以具有包可見性,或公有可見性。

內部類的特殊語法規則

使用外圍類引用的表達式

OuterClass.this

內部對象的構造器:

outerObject.new InnerClass (construction parameters)

最新構造的 TimePrinter 對象的外圍類引用被設置爲創建內部類對象的方法中的this 引用。這是一種最常見的情況。通常,this 限定詞是多餘的。不過,可以通過顯式地命名將外圍類引用設置爲其他的對象。

TalkingClock jabberer = new TalkingClock(1000, true);
TalkingOock.TimePrinter listener = jabberer.new TimePrinter();

在外圍類的作用域之外,可以這樣引用內部類:

OuterClass.InnerClass

局部內部類

可以在一個方法中定義局部類

public void start() {
    class TimePrinter inpleients ActionListener
    {
	    public void actionPerformed(ActionEvent event) {
	    System.out.println("At the tone, the tine is " + new Date());
	    if (beep) Toolkit.getDefaultToolkit.beep():
	     } 
	     }
	    ActionListener listener = new TimePrinter();
	    Timer t = new Timer(interval, listener); 
	    t.start(); 
}

局部類不能用 public 或 private 訪問說明符進行聲明。它的作用域被限定在聲明這個局部類的塊中。
局部類有一個優勢, 即對外部世界可以完全地隱藏起來。 即使 TalkingClock 類中的其他代碼也不能訪問它。除 start 方法之外, 沒有任何方法知道 TimePrinter 類的存在。

匿名內部類

將局部內部類的使用再深人一步。 假如只創建這個類的一個對象,就不必命名了。這種類被稱爲匿名內部類(anonymous inner class)。

public void start(int interval, boolean beep) {
ActionListener listener = new ActionListenerO
{
    public void actionPerformed(ActionEvent event) {
	    System.out.println("At the tone, the time is " + new Date());
	    if (beep) Toolkit.getDefaultToolkit().beep(); 
	    } 
	    };
	    Timer t = new Timer(interval, listener);
	    t.start();
}

多年來,Java 程序員習慣的做法是用匿名內部類實現事件監聽器和其他回調。如今最好還是使用 lambda 表達式。

public void start(int interval, boolean beep) {
	Timer t = new Timer(interval, event -> {
	Systea.out.printlnC'At the tone, the time is " + new Date());
	if (beep) Toolkit.getDefaultToolkit().beep(); 
	});
	t.start();
}

下面的技巧稱爲“ 雙括號初始化” (double brace initialization), 這裏利用了內部類語法。假設你想構造一個數組列表,並將它傳遞到一個方法:

ArrayList<String> friends = new ArrayList<>();
friends,add("Harry");
friends,add("Tony");
invite(friends);

如果不再需要這個數組列表,最好讓它作爲一個匿名列表。

invite(new ArrayList<String>() {{ add("Harry"); add("Tony"); }});

注意這裏的雙括號。外層括號建立了 ArrayList 的一個匿名子類。內層括號則是一個對象構造塊

靜態內部類

有時候, 使用內部類只是爲了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類對象。爲此,可以將內部類聲明爲 static, 以便取消產生的引用。
靜態內部類的對象除了沒有對生成它的外圍類對象的引用特權外, 與其他所冇內部類完全一樣。

class ArrayAlg{
	...
	public static class Pair{
	...
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章