嵌套类(Nested Class)

来源:互联网 发布:mac vi保存退出 编辑:程序博客网 时间:2024/06/06 19:34

嵌套类

  • 静态嵌套类
  • 非静态嵌套类(内部类【inner class】)
class OuterClass{    //...    class NestedClass{        //...    }}
class OuterClass{    //...    static class NestedClass{}    class InnerClass{}}

     嵌套类是它所在封装类的一个成员。非静态嵌套类(内部类)可以访问封装类的其他成员,包括声明为private的成员。静态嵌套类不能访问该风状态的其他成员。作为外部类的一个成员,一个嵌套类可以被声明为private,public,protected或者package private。

为什么使用嵌套类?

使用嵌套类的主要原因:

  • 它将仅在一个地方使用的逻辑类组合在一块。如果一个类仅在另外一个类中使用,那么,前者在逻辑上绑定到后者上使得两者在一块。像帮助类的嵌套使得他们的包更加合理化。
  • 提高封装性。假如两个顶级类A和B,B需要访问A的private成员,通过将B嵌套在A中,A的成员可以被成名为private并且B可以访问它们。另外,B类也被隐藏起来了。
  • 提高可读性和维护性。嵌套类使得它存在的地方靠近定义的地方。

静态嵌套类
     和类方法和变量一样,一个静态嵌套类和它的外部类是相关联的。类似静态类方法,一个静态嵌套类不能直接引用它所在封装类实例的变量和方法。它只能通过一个对象引用来使用它们。
     备注:一个静态嵌套类和它封装类的实例成员关系,就像任何其他顶级类一样。实际上,一个静态嵌套类行为和顶级类是一样的。

     静态嵌套类使用封装类名字来访问:

OuterClass.StaticNestedClass

创建一个静态嵌套类对象,语法如下:

new OuterClass.StaticNestedClass();

内部类
和实例方法和实例变量一样,一个内部类和封装类的实例有关系,可以直接访问封装类实例的方法和属性。同样,因为一个内部类和封装类的实例相关,它不能定义任何静态成员

内部类的实例存在于外部类的实例中,下面例子:

class OuterClass{    class InnerClass{}}

一个内部类的实例仅能够存在于外部类的实例中,并且可以直接访问外部类的方法和属性。
为了实例化一个内部类,你必须要先实例化外部类,创建内部类的语法如下:

OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();

存在两种内部类:本地类(local classes)和匿名内部类(anonymous classes)

覆盖/隐藏(Shadowing)

如果在特拟定范围内(如内部类或者方法)的一个类型(如成员变量或者参数名称)定义和封装类的其他声明有相同的名字。然后这个声明将会覆盖掉封装类的声明。一个隐藏声明,你不能单独用它的声明来引用,如下ShadowTest所示:

public class ShadowTest{    public int x = 0;    class FirstLevel{        pulbic 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=23this.x=1ShadowTest.this.x=0

这个例子中定义了三个名称为x的变量:类ShadowTest的成员变量,内部类FirstLevel的成员变量,和方法methodInFirstLevel的参数。方法methodInFirstLevel的参数x覆盖了内部类FirstLevel的成员变量,因此,当你在methodInFirstLevel中使用变量x,它引用的是方法参数。要用内部类FirstLevel成员变量,需要使用关键字this:

System.out.println("this.x="+this.x);

引用更大范围变量:

System.out.println("ShadowTest.this.x="+ShadowTest.this.x);

序列化
本地类和匿名类的序列化,强烈不推荐使用。当Java编译器编译指定构造器,如内部类,它创建复合构造;类、方法、属性和其他构造器,它们在源代码中没有相应的构造。复合构造让Java编译器可以实现新的Java语言特性而不用修改jvm。然而,复合构造非常不同于Java编译器实现,这意味着.class文件实现也非常不同。因此,在一个不同的jre实现中,如果你序列化一个内部类,可能会有容错问题。

1 0