内部类是定义在另一个类中的类
为什么要使用内部类,主要有以下两个原因 :
- 内部类可以对同一个包中的其他类隐藏
- 内部类方法可以访问定义这个类的作用域中的数据,包括原本私有的数据
public class TailingClock{
private int interval;
private boolean beep;
public class TimePrinter implements ActionListener{
...
}
}
这里的TimePrinter类位于TailingClock类内部,但是,并不代表每一个TalkingClock类都有一个TimePrinter实例,其实例化仍然需要TalkingClock中的代码实现
一个内部类方法可以访问自身的数据字段,也可以访问创建他的外围类的数据字段
但是,不能通过常规的手段来访问到外围类的数据字段
这里需要用到outer关键字,outer代表着这个内部类的隐式引用,也就是在TimePrinter类中可以这样写
public class TimePrinter implements ActionListener{
public void actionPerformed(ActionEvent event){
if(outer.beep)
Toolkit.getDefaultToolkit().beep();
}
}
内部类可以改变它的外围引用
var jabber = ner TalkingClock(1000,true);
TalkingClock.TimePrinter listener = jabber.new TimePrinter();
局部内部类
有时候,某一个类只在调用某一个方法的时候使用了一次
遇到这种情况,可以在一个方法中局部地定义这个类
public void start(){
calss TimerPrinter implements ActionListener{
...
}
var listener = new TimerPrinter();//实例化
var timer = new Timer(interval,listener);//传递这个类
timer.start();
}
声明局部时不能有访问说明符(public或private等),局部类的作用域被限定在声明这个局部类的块中
局部类对外部世界完全隐藏,即使是这个方法的所在类也没有办法去访问到他
而且,如果你不使用局部类的话,如果在方法中有一个局部变量,其他类是没有办法访问到他的,除非将局部变量设置为全局变量,而如果你在这个方法中使用一个局部类的话,就可以访问到这个方法中的局部变量了
匿名内部类
使用局部内部类时,通常可以再进一步,假如只想创建这个类的一个对象,甚至不需要为这个类指定名字
public void start(){
var listener = new ActionListener(){
public void actionPerformed(ActionEvent e){
...
}
}
}
这段代码看起来很奇怪,先不论ActionListener本来是一个接口但是却好像new了一个出来,在ActionListener的构造函数之后本来应该截至的,但是它还增加了一个大括号并且在里面填入了很多内容,而在大括号里面又写了一段好像是在构建一个函数的代码
其实都不是的,它的含义是,创建一个类的新对象,这个对象实现了ActionListener接口,需要实现的方法在actionPerformed在括号{}内定义,而这个类的名字他没有写,所以new根本不是指ActionListener接口(接口本身也无法被实例化),而是指一个匿名内部类
一般的,匿名内部类语法如下
new SuperType(construction parameters){
inner class menthods and data;
}