常规内部类和普通类最大的不同就是,它能访问(这里,访问的意思包括读和写)外部类的私有实例域。下面是一个例子:
package innerclass;
public class Outer {
private boolean isPrint;
public Outer(boolean isPrint) {
this.isPrint = isPrint;
}
public void useInnerMethod() {
Outer.Inner inner = this.new Inner(); // 等价于Inner inner = new Inner();
inner.innerPrint();
}
// 与外部类不同,内部类可以用private修饰
public class Inner {
public void innerPrint() {
// 内部类可以访问外部类的私有实例域
if (Outer.this.isPrint) {//等价于if (isPrint) {
System.out.println("print ture");
} else {
System.out.println("print flase");
}
}
}
}
package innerclass;
public class TestOuter {
public static void main(String[] args) {
// TODO Auto-generated method stub
Outer outer = new Outer(false);
outer.useInnerMethod();
// 内部类对象必须依赖外部类对象
Outer outer1 = new Outer(true);
Outer.Inner inner = outer1.new Inner(); // 等价于Inner inner = outer1.new Inner();
inner.innerPrint();
}
}
运行TestOuter的结果为:
print flase
print ture
内部类为何能访问访问外部类的私有实例域呢?我们反编译编译Outer类得到的两个类文件来得到答案。
在命令行运行javap -private Outer,得到如下结果:
Warning: Binary file Outer contains innerclass.Outer
Compiled from "Outer.java"
public class innerclass.Outer {
private boolean isPrint;
public innerclass.Outer(boolean);
public void useInnerMethod();
static boolean access$0(innerclass.Outer);
}
在命令行运行javap -private Outer$Inner,得到如下结果:
Warning: Binary file Outer$Inner contains innerclass.Outer$Inner
Compiled from "Outer.java"
public class innerclass.Outer$Inner {
final innerclass.Outer this$0;
public innerclass.Outer$Inner(innerclass.Outer);
public void innerPrint();
}
通过阅读反编译的结果,我们知道,编译器在内部类中添加了一个外部类对象的引用:
final innerclass.Outer this$0;
我们知道,即使有了一个对象的引用,也不能通过.(点)直接操作对象的私有实例域,那么内部类是如何做到的呢?我们看到编译器还在Outer类中添加了一个方法:
static boolean access$0(innerclass.Outer);
内部类就是通过这个方法实现访问外部类的私有实例域的。