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

2014-11-23 20:27:42 · 作者: · 浏览: 29
1 简介
内部类就是定义在其他类中的类, 那么为什么要具有这样的特性呢
内部类能够访问该类外部类的所有成员变量, 以及所有方法, 包括私有的成员.
内部类将它的可见性进行了一定的隐藏, 使得同一个package中的其他类不能直接的对其进行访问.
下面将通过一个个案例来对内部类进行深入的解释, 欢迎看客的各种建议.
2 案例
一个小学教室, 数学老师在教小朋友们数数字, 老师说一个数, 如n, 那么小朋友就从1开始以n为间隔进行数数, 如1, 1+n, 1+n+n, …, 老师说停, 那么小朋友便停止数数 (这里假设小朋友的数数速度是均匀的, 1 number/s).
2.1 不使用内部类的实现
复制代码
import java.awt.event.*;
import javax.swing.*;
public class Demo {
public static void main(String[] args) {
// 为了示例的简洁
// 这里直接默认学生的名字为: xiao ming
// 数数的步长为10
Student s = new Student("xiao ming");
s.startCount(10);
JOptionPane.showMessageDialog(null, "停止数数.");
System.exit(0);
}
}
/**
学生类, 仅包含学生的名字信息
*/
class Student {
public Student(String name) {
this.name = name;
}
public void startCount(int step) {
// 为了能够知道谁在计数
// 这里需要将学生的名字信息传递给计数类
ActionListener count = new Counting(step, name);
Timer t = new Timer(1000, count);
t.start();
}
private String name;
}
/**
用来完成每隔一定时间实施数数功能
*/
class Counting implements ActionListener {
public Counting(int step, String name) {
this.step = step;
this.name = name;
num = 1;
}
// 进行数数
public void actionPerformed(ActionEvent event) {
System.out.println(name + " count: " + num);
num = num + step;
}
private int step;
private int num;
private String name;
}
复制代码
从上面的示例中, 我们发现, 如果使用外部类进行实现该功能, 那么该计数类将能够被包中其他的类使用, 降低了该功能的封装性. 这正好可以通过使用内部类的方法进行解决.
2.2 内部类的实现
复制代码
import java.awt.event.*;
import javax.swing.*;
public class Demo {
public static void main(String[] args) {
// 为了示例的简洁
// 这里直接默认学生的名字为: xiao ming
// 数数的步长为10
Student s = new Student("xiao ming");
s.startCount(10);
JOptionPane.showMessageDialog(null, "停止数数.");
System.exit(0);
}
}
/**
学生类, 仅包含学生的名字信息
*/
class Student {
public Student(String name) {
this.name = name;
}
public void startCount(int step) {
// 为了能够知道谁在计数
// 这里需要将学生的名字信息传递给计数类
ActionListener count = new Counting(step);
Timer t = new Timer(1000, count);
t.start();
}
private String name;
/**
用来完成每隔一定时间实施数数功能
内部类中可以直接使用外部类中的成员变量 - name
*/
private class Counting implements ActionListener {
public Counting(int step) {
this.step = step;
num = 1;
}
// 进行数数
public void actionPerformed(ActionEvent event) {
System.out.println(name + " count: " + num);
num = num + step;
}
private int step;
private int num;
}
}
复制代码
这样包内的其他类就不能直接调用Counting类了.
3 有趣的事情开始发生了
用外部类实现的示例编译后产生的类文件有:
Demo.class, Student.class, Counting.class
而内部类示例编译后产生的类文件为:
Demo.class, Student.class, Student$Counting.class
单单从编译后的结果来看, java 虚拟机在具体类的载入以及实现过程中, 应该和"外部类实现","内部类实现"没有关系. 那么"Student$Counting.class"这个神奇的类中到底包含了什么呢
下面就来揭示这个秘密吧, 采用的工具为java decompiler.
反编译后的结果如下, Student$Counting.class:
https://www.cppentry.com/upload_files/article/76/1_z3prf__.jpg #studentcount