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{
	...
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章