一、为何使用内部类
- 内部类可以访问外部类中的所有数据,包括声明为private的数据。
- GUI中的回调方法callback时,可以让组件共享一个对象,其中包含当指定事件触发时执行的操作代码,这个对象可以实现一个事件处理接口或继承一个抽象适配器类。
- 对包中的其他类实现隐藏。
- 匿名内部类有组与单一组件的事件处理代码的简化。
二、内部类的特殊语法
public class TalkClock {
private int interval;
private boolean beep;
public TalkClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start() {
ActionListener listener = new TimerPrinter();
Timer t = new Timer(interval, listener);
t.start();
}
public class TimerPrinter implements ActionListener {
public void actionPerformed(ActionEvent e) {
Date date = new Date();
System.out.println("the time is: "+date);
if(beep)
Toolkit.getDefaultToolkit().beep();
}
}
public static void main(String[] args) {
TalkClock c = new TalkClock(10000, true);
c.start();
JOptionPane.showMessageDialog(null, "wow");
System.exit(0);
}
}
编译之后会发现生成两个类,TalkClock$TimerPrinter.class和TalkClock.class。使用JD-GUI打开class文件:其中TalkClock$TimerPrinter.class文件如下
public class TalkClock$TimerPrinter implements ActionListener {
public void actionPerformed(ActionEvent paramActionEvent) {
Date localDate = new Date();
System.out.println("the time is: " + localDate);
if (TalkClock.access$000(this.this$0))
Toolkit.getDefaultToolkit().beep();
}
}
TalkClock.class文件如下
public class TalkClock {
private int interval;
private boolean beep;
public TalkClock(int paramInt, boolean paramBoolean) {
this.interval = paramInt;
this.beep = paramBoolean;
}
public void start() {
TalkClock.TimerPrinter localTimerPrinter = new TalkClock.TimerPrinter();
Timer localTimer = new Timer(this.interval, localTimerPrinter);
localTimer.start();
}
public static void main(String[] paramArrayOfString) {
TalkClock localTalkClock = new TalkClock(10000, true);
localTalkClock.start();
JOptionPane.showMessageDialog(null, "wow");
System.exit(0);
}
public class TimerPrinter implements ActionListener {
public void actionPerformed(ActionEvent paramActionEvent) {
Date localDate = new Date();
System.out.println("the time is: " + localDate);
if (TalkClock.this.beep)
Toolkit.getDefaultToolkit().beep();
}
}
}
可以看到外部类可以通过
TalkClock.TimerPrinter localTimerPrinter = new TalkClock.TimerPrinter();
也就是:outerClass.innerClass的形式访问内部类。同时内部类也可以通过TalkClock.this.beep,也就是形如outerClass.this.field的形式访问外部类的参数。
接下来,我们使用命令行:
javap -private TalkClock$TimerPrinter
结果如下:
我们,会发现使用命令行会多出一个由编译器编译指定的一个this$0参数。回顾一下TalkClock$TimerPrinter.class文件中出现的TalkClock.access$000(this.this$0)代码。再次对TalkClock文件使用上述命令,来看看是不是有变化呢
javap -private TalkClock
不出所料,javap为我们提供了一个不可见的access$000方法,这是否存在某些安全隐患呢,事实上,这需要对类文件有这深入的了解才可能做到。