Java 嵌套类
嵌套类, 是嵌套在 Java 一个类的内部的类.
嵌套类可以通过两种形式来声明:
- 使用
static
修饰的嵌套类, 我们称之为静态嵌套类(Static Nested Class) - 不使用
static
修饰的嵌套类, 我们称之为内部类(Inner Class) 或 非静态嵌套类 (Non-Static Nested Class)
因此, 嵌套类的定义有以下两种形式:
class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... } }
嵌套类是它的封闭类(外部类)的成员,其中内部类(非静态嵌套类)可以访问其外部类的其他成员,包括私有成员. 静态嵌套类则不具备这样的能力.
嵌套类可以使用 public
, private
, protected
及默认修饰符修饰, 而普通类只能声明为共有和包私有.
为什么要使用嵌套类
使用嵌套类, 有以下原因:
- 使包的结构更加简洁, 如果一个类仅对另一个类有用, 那么使用嵌套类是合乎逻辑的.
- 提供了更丰富的封装方式, 基于嵌套类的访问修饰符, 我们可以做到更细致的访问控制.
- 引导提升代码的可读性和可维护性, 嵌套类与外部类的位置更靠近了.
静态嵌套类的调用
静态嵌套类可以通过外部类名来调用, 通用示例如下:
OuterClass.StaticNestedClass
初始化示例如下:
OuterClass.StaticNestedClass nestedClass = new OuterClass.StaticNestedClass()
内部类的调用
内部类则必须通过外部类的实例来调用了, 初始化方法如下:
OuterClass outerClass = new OuterClass(); OuterClass.InnerClass innerClass = outerClass.new InnerClass();
需要注意的是 这里的 new
是放在 OuterClass
的示例对象 outerClass
后的.
内部类调用外部类的其他成员
首先我们定义一个带有内部类 Engine 的外部类 Yi21Car, 定义如下:
package com.yi21.course; public class Yi21Car { //油量 L private double oil = 0; private Engine engine; private class Engine { private final double EVERY_TIME = 0.01; //烧油 public void burn() { if (oil < EVERY_TIME) { throw new RuntimeException("No Gas!"); } oil -= EVERY_TIME; } } public Yi21Car(double oil) { this.oil = oil; engine = new Engine(); } public void stepAccelerator() { engine.burn(); } public double getRestOil() {
return oil; } }
我们的定义如下:
- 定义外部类 - 汽车类:
Yi21Car
- 定义了属性
oil
, 表示汽车的汽油量 - 定义了一个内部类, 汽车的引擎
Engine
Engine
定义了一个burn()
方法, 表示烧油, 为了简化过程, 我们规定每次都烧 0.01 L 汽油, 如果汽油不够就抛出异常, 表示没油了.- 再定义了
Yi21Car
的构造方法, 构造方法中, 设定了车的汽油存量oil
以及初始化了内部类Engine
. - 定义外部类的方法
stepAccelerator()
表示踩油门, 踩油门真实的汽车当然会做很多工作, 但我们在此错了简化, 只有发动机烧油, 于是调用了engine
的blur()
方法. - 最后声名了
getRestOil()
方法, 用于查看剩多少油.
然后我们在外部通过以下方法调用:
Yi21Car car = new Yi21Car(50); car.stepAccelerator(); System.out.println(car.getRestOil()); car.stepAccelerator(); System.out.println(car.getRestOil()); car.stepAccelerator(); System.out.println(car.getRestOil());
初始化一辆车 Yi21Car
, 然后踩三次油门, 分别看看还剩多少油, 结果如下:
49.99 49.980000000000004 49.970000000000006
由此我们可知, 内部类 Engine
完成了对外部类 Yi21Car
的成员变量 oil
的访问.
当时需要注意的是, 如果 Engine
内部也定义 了一个 oil
成员变量, 那么再通过 Engine
访问 oil
的话访问的就是 Engine
的 oil
了, 而不是 Yi21Car
的 oil
了. 那如果我想通过内部类, 访问外部类的同名成员要怎么办呢? 两个方法:
- 避免内部类的外部的成员同名
- 通过 外部类的类名 +
.this
调用, 比如Yi21Car.this.oil
序列化
在运行时反编译序列化的内部类可能会存在兼容性的问题, 因此强烈不建议对内部类(包括本地类和匿名类进行)进行序列化.
以上就是 Java 嵌套类的全部内容.
下一节请看: Java 运算符