【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();
		}
		
	}
}

结果:
在这里插入图片描述

捐赠

若你感觉读到这篇文章对你有启发,能引起你的思考。请不要吝啬你的钱包,你的任何打赏或者捐赠都是对我莫大的鼓励。

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