[java] 深入理解内部类: inner-classes(三)

2014-11-23 20:27:42 · 作者: · 浏览: 32
System.out.println(" " + type.getName() + " " + name + ";");
}
}
}
复制代码
3.2 解释为什么能够在内部类直接访问外部类的成员变量
运行:
javac ReflectionTest.java
java ReflectionTest 'Student$Counting'
输出为:
class Student$Counting {
public Student$Counting(Student, int);
public void actionPerformed(java.awt.event.ActionEvent);
private int step;
private int num;
final Student this$0;
}
然后再结合该类的反编译的结果图, 就可以发现通过在构造函数中增加Student变量, 并且赋值给了 final Student this$0, 这就解释了 为什么在内部类中能够访问外部类的成员变量 , 但是又为什么在内部类中能够访问 外部类的私有变量 呢
让我们来看一下Student$Counting中另一处神奇的地方.
System.out.println(Student.access$000(this.this$0) + " count: " + this.num);
可见, Student类中又多了一个成员函数, 但是在 Java Decompiler软件的结果中并没有发现, 于是再次采用了ReflectionTest, 其结果为:
class Student {
public Student(java.lang.String);
public void startCount(int);
static java.lang.String access$000(Student);
private java.lang.String name;
}
可见编译后的Student中出现了一个新的静态方法, 我们可以很容易的猜测到该静态方法的实现类似如下:
static String access$000(Student s) {
return name;
}
编译器通过这样的方式实现了从一个类中访问另一个类的私有变量, 那么通过直接修改class文件, 使得获取或改变类中的私有变量成为了可能, 当然要进行实现需要更强大的能力了.
4 局部内部类实现
使用局部内部类在代码编写的过程中其他的类均失去了对它的调用能力, 此时Student如下:
复制代码
/**
学生类, 仅包含学生的名字信息
*/
class Student {
public Student(String name) {
this.name = name;
}
public void startCount(final int step) {
/**
用来完成每隔一定时间实施数数功能
局部内部类中可以直接使用外部类中的成员变量 - name
还可以直接调用final的局部变量
*/
class Counting implements ActionListener {
// 进行数数
public void actionPerformed(ActionEvent event) {
System.out.println(name + " count: " + num);
num = num + step;
}
private int num = 1;
}
// 为了能够知道谁在计数
// 这里需要将学生的名字信息传递给计数类
ActionListener count = new Counting();
Timer t = new Timer(1000, count);
t.start();
}
private String name;
}
复制代码
此时编译后新生成的类有:
Demo.class Student$1Counting.class Student.class
继续使用ReflectionTest, 分别对后两个类文件进行处理, 结果如下:
// Student$1Counting.class
class Student$1Counting {
Student$1Counting(Student, int);
public void actionPerformed(java.awt.event.ActionEvent);
private int num;
final int val$step;
final Student this$0;
}
// Student.class
class Student {
public Student(java.lang.String);
public void startCount(int);
static java.lang.String access$000(Student);
private java.lang.String name;
}
可见通过编译后, 局部变量和外部类, 都成为了内部类的成员变量. 局部变量的可用性, 使得整个程序更加的简单明了.
5 匿名的内部类
匿名内部类的实现也可以采用类似的方式实现.
匿名内部类的实现格式如下:
new SuperType(construction parameters) {
inner class methods and data
}
其实, 可以通过一下方式使得对匿名内部类有一个更清楚的了解:
Person count = new class extends Person("") {...}; // 该形式并不是真正的java格式,只是为了帮助理解
Person count = new Person("") {...}; // 这才是正确的格式
匿名内部类, 还有一个比较常用的方法就是利用初始化块对一个变量进行初始化:
private List maleList = new ArrayList() {
// 初始化块
{
add("Machael");
add("Scorfield");
add("Other");
}
};
想要更清楚的理解上述的初始化块, 可以继续看下面的示例:
复制代码
class Person {
private String nam