内部类
内部类是定义在另一个类中的类,使用内部类的主要原因:
内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据
内部类可以对同一个包中的其他类隐藏起来
当想要定义一个回调函数而且不想编写大量代码时,使用匿名内部类比较便捷
内部类示例代码:
|
|
这里内部类访问了外层类的实例域,实际上内部类的对象总有一个隐式引用,它指向了创建它的外部类对象,当然上述代码中TimPrinter类可以设置成private,因为只有TalkingClock类的方法创建了TimePrinter。当然我们还可以在外部类的外部新创建一个内部类的实例
|
|
内部类是一种编译器行为,与jvm无关,编译器会把内部类翻译成用$
分隔外部类名和内部类名的常规类文件,而jvm对此一无所知,例如之前内部类TimePrinter类将被翻译成TalkingClock$TimePrinter.class
,如果利用反射打印内部类的变量方法信息:
|
|
编译器为了引用外围类,声称了附加实例域this$0
,编译器为内部类生成了默认的构造器:
|
|
这里将外围对象的引用为this$0
,因此内部类的actionPerformed方法。
|
|
既然内部类被翻译成古怪的常规类,但是jvm对此一无所知,那么内部类又如何获得额外的访问权限呢(比如获得外部类的私有域),我们再次利用反射查看外部类TalkingClock:
|
|
可以看到可以通过调用access$0
方法获得beep的值,但是这样确实存在安全隐患
局部内部类
上例中TimePrinter累只在start方法中创建这个类型对象时使用了一次,因此可以定义一个局部类
|
|
下面这个例子是局部内部类访问局部变量,注意访问的局部变量必须是final
|
|
匿名内部类
有时只是为了创建这个类的一个对象,就没有必要命名了
|
|
语法格式:
|
|
当然这里SuperType可以是接口,于是内部类就要实现这个接口
静态内部类
|
|
本例中内部类Pair没有引用其外部类,所以这里设置为static,注意只有内部class才可能声明为static,静态内部类不能引用其外部类对象,而且这里内部类必须设置成static
,因为在一个静态的minmax方法中new了Pair对象,非静态的内部类要“借助”与一个外部类对象。