内部类是定义在其他类内部的类,其存在的原因
- 内部类对象能够访问创建它的对象的私有数据
- 能够隐藏起来,不为同一包中的其他类可见
- 可以方便地定义运行时回调
- 编写事件驱动的程序时用起来很方便
public class InnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
BankAccount account = new BankAccount(10000);
account.start(10);
JOptionPane.showMessageDialog(null, "quit?");
System.exit(0);
}
}
class BankAccount{
private double balance;
public BankAccount(double b) {
balance = b;
}
public void start(double rate) {
ActionListener adder = new InterestAddr(rate);
Timer t = new Timer(1000, adder);
t.start();
}
//内部类是私有的
private class InterestAddr implements ActionListener{
private double rate;
public InterestAddr(double r) {
rate = r;
}
@Override
public void actionPerformed(ActionEvent e) {
//可以访问创建它的外部对象的数据字段
double interest = balance * rate / 100;
balance += interest;
System.out.println("balance = " + balance);
}
}
}
内部类是私有的
编译器会把内部类编译成使用$分隔外部类名和内部类名的常规class文件
BankAccount$InterestAddr.class
局部内部类是定义在一个方法里的内部类
仔细观察BankAccount例子中的代码,发现只需要InterestAddr的名字的地方就是start方法,因此可以在方法里定义局部类
class BankAccount{
private double balance;
public BankAccount(double b) {
balance = b;
}
public void start(double rate) {
class InterestAddr implements ActionListener{
private double rate;
public InterestAddr(double r) {
rate = r;
}
@Override
public void actionPerformed(ActionEvent e) {
//可以访问创建它的外部对象的数据字段
double interest = balance * rate / 100;
balance += interest;
System.out.println("balance = " + balance);
}
}
ActionListener adder = new InterestAddr(rate);
Timer t = new Timer(1000, adder);
t.start();
}
}
局部类不会使用访问指示符(如public或者private)来声明,它的范围总是限定在声明它的程序块中。
相对于其他内部类而言,局部类还可以访问局部变量,不过,那些局部变量必须声明为final。
class BankAccount{
private double balance;
public BankAccount(double b) {
balance = b;
}
public void start(final double rate) {
class InterestAddr implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
//可以访问创建它的外部对象的数据字段
double interest = balance * rate / 100;
balance += interest;
System.out.println("balance = " + balance);
}
}
ActionListener adder = new InterestAddr();
Timer t = new Timer(1000, adder);
t.start();
}
}
start控制流:
1)调用start方法
2)调用内部类InterestAddr的构造器初始化对象变量adder
3)把adder引用传递给Timer构造器,定时器启动,start方法退出。现在start方法的rate参数变量已经不存在了。
4)然后actionPerformed方法调用double interest = balance * rate / 100;
为了让actionPerformed方法中的代码能工作,InterestAddr类必然在释放start方法的局部变量rate之前给它做了一份拷贝,这也正是实际的情形。局部类的方法只能使用final的局部变量,因为这样的变量不能被修改,所以局部变量和局部类所建立的变量拷贝总是具有相同的值。
匿名内部类
对局部内部类的使用还可以走的更远,如果你只需要为内部类建立一个对象,那么甚至不必为该类指定一个名字。我们把这种类称作匿名内部类。
class BankAccount{
private double balance;
public BankAccount(double b) {
balance = b;
}
public void start(final double rate) {
ActionListener adder = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double interest = balance * rate / 100;
balance += interest;
System.out.println("balance = " + balance);
}
};
Timer t = new Timer(1000, adder);
t.start();
}
}