javaSE_8系列博客——Java语言的特性(三)--类和对象(15)--嵌套类
来源:互联网 发布:手机数据恢复哪个好 编辑:程序博客网 时间:2024/05/29 17:29
Java编程语言允许您在另一个类中定义一个类。这样的一个类叫做一个嵌套类,例如:
class OuterClass { ... class NestedClass { ... }}
嵌套类分为静态和非静态两类。声明为静态的嵌套类称为静态嵌套类。非静态嵌套类称为内部类。
class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... }}
嵌套类是其封闭类的成员。非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有的。静态嵌套类无法访问封闭类的其他成员。作为OuterClass的成员,嵌套类可以被声明为private,public,protected或private私有。 (回想一下,外部类只能被声明为public或package private。)
为什么使用嵌套类
使用嵌套类的令人信服的原因包括:
- 这是一种仅在一个地方使用逻辑上分组的类的方法:如果类仅对另一个类有用,则将其嵌入该类并将其保持在一起是合乎逻辑的。嵌套这样的“助手类”使他们的包更加精简。
- 它增强了封装性:考虑两个顶级类A和B,其中B需要访问A中声明为私有的的成员。通过在类A中隐藏B类,A的成员可以被声明为private,B可以访问它们。另外,B本身也可以保持对外部的不可见,隐蔽起来。
- 它可以带来具有更好的可读性和可维护性的代码:将顶级类中的小类嵌套使得代码更接近使用的位置。
静态嵌套类
与类方法和变量一样,静态嵌套类与其外部类相关联。和静态类方法一样,静态嵌套类不能直接引用它的封闭类中定义的实例变量或方法:它只能通过对象引用来使用它们。
注意:
静态嵌套类与其外层类(和其他类)的实例成员就像任何其他顶级类一样进行交互。实际上,静态嵌套类是行为上的顶级类,已经嵌套在另一个顶级类中以便于打包。
使用封闭类名访问静态嵌套类:
OuterClass.StaticNestedClass
例如,要为静态嵌套类创建一个对象,请使用以下语法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
内部类
与实例方法和变量一样,内部类与其封闭类的实例相关联,并可以直接访问该对象的方法和字段。另外,因为内部类与一个实例相关联,所以它不能定义任何静态成员本身。 作为内部类的实例的对象存在于外部类的实例中。思考一下下面这种类型的代码:
class OuterClass { ... class InnerClass { ... }}
InnerClass的一个实例只能在OuterClass的一个实例中存在,并且可以直接访问其封闭实例的方法和字段。 要实例化一个内部类,必须首先实例化外部类。然后,使用以下语法在外部对象内创建内部对象:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
内部类有两种特殊类:本地类和匿名类。
遮盖(覆盖)
如果特定作用域范围(例如内部类或方法定义)中的类型声明(例如成员变量或参数名称)与封闭范围中的另一个声明具有相同的名称,那么封闭类中的变量将被内部类或者方法定义中的变量遮盖。您不能仅仅通过其名称来引用一个被遮盖的变量声明。以下示例ShadowTest演示如下:
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 = 23this.x = 1ShadowTest.this.x = 0
此示例定义了名为x的三个变量:ShadowTest类的成员变量,内部类FirstLevel的成员变量和方法methodInFirstLevel中的参数。定义为methodInFirstLevel方法的参数的变量x遮盖了内部类FirstLevel的变量。因此,当在methodInFirstLevel方法中使用变量x时,它将引用method参数。要引用内部类FirstLevel的成员变量,请使用关键字this来表示使用封闭类:
System.out.println("this.x = " + this.x);
请参考包含较大范围的成员变量与其所属的类名称。例如,以下语句从方法methodInFirstLevel访问类ShadowTest的成员变量:
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
序列化
强烈反对内部类的序列化,包括本地和匿名类。当Java编译器编译某些构造(如内部类)时,会创建合成结构 ; 这些是在源代码中没有相应构造的类,方法,字段和其他结构。合成结构使Java编译器能够实现新的Java语言功能,而不会更改JVM。然而,合成结构可以在不同的Java编译器实现之间变化,这意味着.class文件也可以在不同的实现之间变化。因此,如果序列化内部类,然后使用不同的JRE实现对其进行反序列化,则可能会遇到兼容性问题。有关在编译内部类时生成的合成结构的更多信息,请参阅“获取方法参数名称”部分中的“隐式和合成参数”部分。
- javaSE_8系列博客——Java语言的特性(三)--类和对象(15)--嵌套类
- javaSE_8系列博客——Java语言的特性(三)--类和对象(16)--嵌套类(内部类的示例)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(17)--嵌套类(本地/局部类)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(18)--嵌套类(匿名类)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(19)--嵌套类(Lambda 表达式)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(20)--嵌套类(Lambda 表达式--VS--方法引用)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(9)--对象的创建
- javaSE_8系列博客——Java语言的特性(三)--类和对象(10)--对象的使用
- javaSE_8系列博客——Java语言的特性(三)--类和对象(8)--对象
- javaSE_8系列博客——Java语言的特性(三)--类和对象(3)--类的声明
- javaSE_8系列博客——Java语言的特性(三)--类和对象(13)--理解类的成员
- javaSE_8系列博客——Java语言的特性(三)--类和对象(2)--类(宏观概述)
- javaSE_8系列博客——Java语言的特性(三)--类和对象(1)--概述
- javaSE_8系列博客——Java语言的特性(三)--类和对象(4)--声明成员变量
- javaSE_8系列博客——Java语言的特性(三)--类和对象(5)--定义方法
- javaSE_8系列博客——Java语言的特性(三)--类和对象(11)--从方法返回值
- javaSE_8系列博客——Java语言的特性(三)--类和对象(12)--使用this关键字
- javaSE_8系列博客——Java语言的特性(三)--类和对象(14)--初始化字段
- 【计组】-- 指令系统(1) : 指令格式
- ReactNative系列之十四评分效果的实现
- 语法2
- dp斜率优化 Hdu 3507(Print Article)详细题解
- 接口总结
- javaSE_8系列博客——Java语言的特性(三)--类和对象(15)--嵌套类
- 第七周 CSS3选择符
- 累加器
- hadoop之虚拟机安装hadoop
- Swift-通过 Emoji 来理解 Swift 高阶函数
- GDAL+qwt直方图显示
- 在CentOS 6.6 64bit上升级GCC到4.8.2版本
- 实验楼linux学习笔记(二):用户及文件权限管理
- APICloud集成微信支付(wxPay第二种方案)