参考《Java核心技术》
Ⅰ、为什么需要内部类
- 内部类可以对同一个包中的其它类隐藏
- 内部类方法可以访问定义这个类的作用域中的数据,包括原本私有的数据
抽象一个TalkingClock类
public class TalkingClock{
private int interval;//发出铃声的间隔
private boolean beep;//开关铃声的标志
public TalkingClock(int interval,boolean beep){...}
public void start(){...}
//这是一个内部类
public class TimePrinter implements ActionListener{
public void beep(ActionEvent event){
//TimePrinter类中没有beep这个成员,但是它依然可以访问外部类中的beep
if(beep)
Toolkit.getDefaultToolkit().beep();
}
}
}
一个内部类方法可以访问自身的数据字段,也可以访问创建它的外围类对象的数据字段
Ⅱ、内部类的特殊语法
为了能访问外围类的数据字段,内部类的对象总有一个隐式引用,指向创建它的外部类对象。注意:这个引用在内部类中是不可见的
1.在内部类中使用外围类引用
表达式:
OuterClass.this//OuterClass指的是外围类具体的类名,不是说所有的外围类都用OuterClass表示
例如beep方法可以这样编写
//这是一个内部类
public class TimePrinter implements ActionListener{
public void beep(ActionEvent event){
//TalkingClock.this是指向外围类TalkingClock的引用
if(TalkingClock.this.beep)
Toolkit.getDefaultToolkit().beep();
}
外围类的引用是在内部类构造器中设置的。编译器会自动给内部类生成一个构造器,这个构造器用于初始化外围类的引用。整个过程是不可见的
2.在内部类外引用内部类
OuterClass.InnerClass//这样引用内部类
可以采用以下语法更加明确地编写内部类对象地构造器:
outerObject.new InnerClass(构造器参数)
由于TalkingClock是一个公共内部类,任何地语音时钟都可以构造一个TimePrinter:
var jabberer = new TalkingClock(1000, true);
TalkingClock.TimePrinter listener = jabberer.new TimePrinter();
3.内部类中方法和字段的规则
- 内部类中声明的所有静态字段都必须是final
- 内部类中不能有static方法
- 若有static方法,它只能访问外围类的静态字段和方法
Ⅲ、局部内部类
局部内部类是对外界完全隐藏的,只有局部内部类所处的代码块可见,甚至外围类中其它代码块也不可见
public void start(){
//没有public或private修饰符就是局部内部类
class TimePrinter implements ActionListener{
public void beep(ActionEvent event){
if(beep)
Toolkit.getDefaultToolkit().beep();
}
}
}
Ⅳ、匿名内部类
如果只想创建类的一个对象,甚至不想指定名字,就可以创建匿名内部类
语法:
new SuperType(构造参数){
...
}
SuperType可以是接口也可以是类
- 接口:匿名内部类必须要实现这个接口。此时不能有任何构造参数
- 类:匿名内部类要扩展这个类
Ⅴ、静态内部类
摘录自:https://www.cnblogs.com/Dean-0/p/11198112.html
- 用static修饰的内部类,称为静态内部类,完全属于外部类本身,不属于外部类某一个对象
- static关键字的作用是把修饰的成员变成类相关,而不是实例相关
- 静态内部类可以包含静态成员,也可以包含非静态成员,但是在非静态内部类中不可以声明静态成员。
- 静态类内部不可以访问外部类的实例成员,只能访问外部类的类成员,即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员
- 外部类不可以定义为静态类,Java中静态类只有一种,那就是静态内部类,顶级类不能用static 修饰
- 外部类如何调用静态内部类中的属性和方法
- 外部类可以通过创建静态内部类实例的方法来调用静态内部类的非静态属性和方法
- 外部类可以直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法
- 如何创建静态内部类实例
在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
在外部类中:内部类名 name = new 内部类名();