【java基礎(四十二)】內部類(一)

內部類(inner class)是定義在另一個類中的類。

爲什麼要使用內部類

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

使用內部類訪問對象狀態

內部類的語法比較複雜。鑑於此情況,我們選擇一個簡單但不太使用的例子說明內部類的使用方法。下面將進一步分析TimerTest示例,並抽象出一個TalkingClock類。構造一個語音時鐘時需要提供兩個參數:發佈通告的間隔和開關鈴聲的標誌。

public class TalkingClock {
	private int interval;
	private boolean beep;
	
	public TalkingClock(int interval, boolean beep) {....}
	public void start() {....};

	// 內部類
	public class TimePrinter implements ActionListener {
		....
	}
}

需要注意,這裏的TimePrinter類位於TalkingClock類內部。這並不意味着每個TalkingClock都有一個TimePrinter實例域。如前所示,TimePrinter對象由TalkingClock類的方法構造。

下面是TimePrinter類的詳細內容。需要注意一點,actionPerformed方法在發出鈴聲之前檢查了beep標誌。

public class TimePrinter implements ActionListener {
	public void actionPerformed(ActionEvent event) {
		System.out.println("At the tone, the time is " + new Date());
		if (beep) Toolkit.getDefaultToolkit.beep();
	}
}

令人驚訝的事情發生了。TimePrinter類沒有實例域或者名爲beep的變量,取而代之的是beep引用了創建TimePrinter的TalkingClock對象的域。這是一種創新的想法。從傳統意義上講,一個方法可以引用調用這個方法的對象數據域。內部類既可以訪問自身的數據域,也可以訪問創建它的外圍類對象的數據域。

爲了能夠運行這個程序,內部類的對象總有一個隱式引用,它指向了創建它的外部類對象。

這個引用在內部類的定義中是不可見的。然而,爲了說明這個概念,我們將外圍類對象的引用稱爲outer。於是actionPerformed方法等價於:

public void actionPerformed(ActionEvent event) {
	System.out.println("At the tone, the time is " + new Date());
	if (outer.beep) Toolkit.getDefaultToolkit().beep();
}

外圍類的引用在構造器中設置。編譯器修改了所有的內部類的構造器。添加一個外圍類引用的參數。因爲TimePrinter類沒有定義構造器,所以編譯器爲這個類生成了一個默認的構造器,如:

public TimePrinter(TalkingClock clock) {
	outer = clock;
}

請再注意一下,outer不是Java關鍵字。我們只是用它說明內部類的機制。

當start方法中創建了TimePrinter對象後,編譯器就會將this引用傳遞給當前的語音時鐘的構造器:

ActionListener listener = new TimePrinter(this);

實例

package cn.freedompc.innerClass;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JOptionPane;
import javax.swing.Timer;

public class InnerClassTest {

	public static void main(String[] args) {
		TalkingClock clock = new TalkingClock(1000, true);
		clock.start();
		
		JOptionPane.showMessageDialog(null, "Quit program?");
		System.exit(0);
	}
	
}

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

結果:
在這裏插入圖片描述

捐贈

若你感覺讀到這篇文章對你有啓發,能引起你的思考。請不要吝嗇你的錢包,你的任何打賞或者捐贈都是對我莫大的鼓勵。

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