Java 嵌套类其实平时很少用,常见的是在多线程和事件处理(例如 Swing,xml 解析)时才需要用到。这里总结一下嵌套类的一些特性。
嵌套类的定义
- 在一个类中定义的类,就称为嵌套类 (nested class)。嵌套类分为两大类,静态嵌套类 (static nested class) 和非静态嵌套类 (non-static nested class),非静态嵌套类也叫内部类 (inner class)。
- 定义嵌套类时可以使用任意访问修饰符 (private, protected, public, 默认),不同于普通类只能使用 public 或者默认。
使用嵌套类的原因
- 嵌套类可作为一种类的逻辑分组方式。例如类 B 只对类 A 有用,那么将 B 作为 A 的内部类更合适。
- 更好的封装。例如上述类 A 和 B,如果 B 是内部类,就可以直接访问 A 的成员。
- 能使代码的可读性和可维护性更好。
静态嵌套类
- 静态嵌套类实际上跟一个普通的类一样,只是因为有利于类的逻辑分组而使用。
内部类
- 内部类跟类的成员相似,可以访问其它类成员(变量或方法)。一个内部类的实例必须存在其外部类的一个实例中。内部类不能有静态成员(静态成员只能在顶级类或静态嵌套类中声明)。
- 内部类出现跟外部类成员变量同名的变量时,默认访问内部类成员,但可以用 "外部类名.this.变量名" 来访问同名的外部类成员。
- 在方法内定义的类称为本地内部类 (local inner class)。
- 如果一个内部类是一个子类(继承了父类或者实现了接口),它可以没有类名,这样的类称为匿名内部类或匿名类 (anonymous [inner] class)。
Outer outer = new Outer();
Inner inner = outer.new Inner(); // 内部类的实例化
匿名类
- 匿名类不能定义构造方法(因为它没有类名),但可以使用初始化块 (initialization block) 进行初始化。如果它继承自某个类,则新建实例时可以调用父类的构造方法(但不能重写)。
- 匿名类如果处于方法内,则使用其包围方法的局部变量时,这个变量必须声明为final。而使用其外部类的成员时则没有这个限制。
// 匿名类例子
public class AnonymousClassTest {
private String str = "outer str";
public static void main(String[] args) {
Base base = new AnonymousClassTest().getBase();
base.print();
}
public Base getBase() {
return new Base(5) { // 匿名类,调用父类的构造函数
private String str = "inner str"; // 跟外部类成员变量同名
{
i = 10; // 可以在初始化块中进行必要的初始化
}
public void print() {
System.out.println("Anonymous print(), i = " + i +
", str = " + AnonymousClassTest.this.str); // 访问同名的外部类成员
}
};
}
}
abstract class Base {
protected int i;
public Base(int i) {
System.out.println("Base Constructor, i = " + i);
}
public abstract void print();
}
参考资源
http://download.oracle.com/javase/tutorial/java/javaOO/nested.html
http://www.java2s.com/Tutorial/Java/0100__Class-Definition/0201__Anonymous-inner-class.htm