1.java语言允许在一个类中定义另一个类。这种类被称为嵌套类。
class OuterClass { ... class NestedClass { ... } }
Terminology: 嵌套类被分为两类:静态和非静态;被声明为静态的嵌套类被叫做静态嵌套类,非静态的嵌套类被称作内部类。
class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... } }
嵌套类是包围它的类的一个成员.。非静态嵌套类(内部类)能够访问它的包围类的其他成员,即使这些成员被声明为私有的。静态嵌套类不能访问它的包围类的其他成员。嵌套类作为外部类的成员之一,可以被声明为private,public,protected,or package private (default) .(注意外部类只能被声明为public或者package private)。
注意:protected :只有在当前类和他的继承类中才能访问。
2.我们为什么使用嵌套类?
-
将类在逻辑上分组的方式之一:如果一个类只对哦另外一个类有用,在逻辑上能够嵌入另一个类,让它们两个类在一块,嵌套这样的帮助类使他们的包内结构更加精简。
-
增强封装性:考虑两个顶层的类 A 和 B, B如果将要访问A中被声明为private 的变量. 通过将B隐藏在A中, B作为A的一个成员,A的成员能被设置为private,并且B能够访问他们,而且B自身能够相对于外面的世界而言隐藏自己。
-
增强代码的可读性和可维护性: 嵌套小的类在顶层类中能够把代码放到使用它的更近的位置。
3.静态嵌套类
就这种类的方法和变量与它的外部类有关(依赖于类)。像静态的方法一样,静态内部类不能直接引用和实例化一个它的外部类的实力或方法。(静态不能访问非静态)只能通过对象引用。
通过外部类来访访问静态嵌套类。
OuterClass.StaticNestedClass
创建静态嵌套类的语法如下:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
4,内部类
就这种类的方法和变量与它的外部类的实例有关(依赖于该类的实例)。它可以直接引用这个对象(实例)的属性和方法。因为内部类与实例有关,所以自身不能定义任何静态成员。
内部类的实例存在于外部类对象之内。
class OuterClass { ... class InnerClass { ... } }
因为内部类的对象存在于外部类的对象之中,所以,它能直接访问 外部类的成员方法和成员变量。
实例化内部类的语法如下:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
5 屏蔽
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
1,传进内部类的参数屏蔽了内部类的成员变量x,挡在内部类中引用X时,它指向了参数x
2,引用内部类成员变量X时,用this.表明了他的包含范围。
3.通过他们所属的外部类的类名.this确定范围引用外部类的成员变量x.
6.序列化
强烈推荐不要进行内部类的序列化,包括本地内部类和 匿名内部类,当java编译器在编译某种例如内部类的结构时会创造很多的合成结构。