Java语言允许你在一个类中再定义类,这样的类,我们称之为嵌套类。格式如下:
class OuterClass{
...
class NestedClass{
...
}
}
术语:嵌套类分为两种,一种是静态;一种是非静态。声明为静态的称之为静态嵌套类;非静态的称之为内部类。
class OuterClass{
...
static class StaticNestedClass{
...
}
class InnerClass{
...
}
}
NestedClass是其OuterClass的成员。对于内部类,可以访问OuterClass的其他成员,尽管成员被定义为private,同样允许访问。然而,静态嵌套类却不能访问。作为OuterClass的一个成员,嵌套类可以定义为private,public,protected。
为什么使用嵌套类?
1、某个类只在单一地方使用,使用嵌套类方便管理;
2、提高了封装性;
3、可读性和可维护性更好。
静态嵌套类
正如类中的方法和变量,静态嵌套类与OuterClass也是有联系。如同类中的静态方法,静态嵌套类不能直接访问OuterClass的实例变量和方法:仅仅可以通过对像的引用来访问它们。
注意:静态嵌套类与OuterClass(以及其他类)的实例成员交互就像跟任何其他顶级类一样。实际上,静态嵌套类就是为了打包方便嵌套在其他顶级类中。
静态嵌套类是通过使用OuterClass类名来访问的:
OuterClass.StaticNestedClass
例如,为静态嵌套类创建一个对象的语法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
内部类
正如类中的实例方法和变量,内部类与OuterClass的实例有联系,并且可以直接访问对象方法和变量。因为内部类与实例有联系,所以它不能定义任何静态成员。
内部类的对象存在于OuterClass的实例对象当中。内部类实例仅仅只能存在一个OuterClass实例当中并且可以直接访问OuterClass实例的方法和属性。
为了实例化一个内部类,你必须首先实例化OuterClass。然后创建一个内部类对象,语法:OuterClass.InnerClass innerObject = outerObject.new InnerClass();
还有两种特殊的内部类:局部类和匿名类。
访问内部类成员变量的经典实例:
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
输出结果:
内部类的序列化x = 23 this.x = 1 ShadowTest.this.x = 0
对于内部类(包括局部类和匿名类)的序列化,Java编译器编译内部类的构造方法时,会创建一个合成的构造函数(synthetic constructs),对于JVM来说,它没有什么不同,但是,不同的Java编译器编译出来的.class文件可能会不同,因此,当你对内部类使用不同的JRE进行序列化和解序列化时可能会面临兼容性的问题。