内部类(Inner Class)就是定义在另外一个类里面的类, 与之对应, 包含内部类的类被称为外部类(Outer Class).
内部类的主要作用:
- 内部类提供了更好的封装, 可以把内部类隐藏在外部类之内, 不允许同一个包中的其他类访问该类
- 内部类的方法可以直接访问外部类的所有数据, 包括私有的数据
- 内部类所实现的功能使用外部类同样可以实现, 只是有时使用内部类更方便
内部类又分为: 成员内部类、静态内部类、方法内部类、匿名内部类 四种
成员内部类
内部类中最常见的就是成员内部类, 也称为普通内部类.
public class HelloWorld { public class Inner { // 此为内部类 } }
- Inner 类定义在 HelloWorld 类的内部, 相当于 Outer Class 的一个成员变量, Inner Class 可以使用任意访问控制符, 如 public 、 protected 、 private 等
- Inner Class 中定义的方法可以直接访问 Outer Class 中的数据, 而不受访问控制符的影响(原因如上面那条)
- 创建内部类对象, 不能直接 new, 必须使用__外部类对象__来创建内部类对象, 即: 内部类 对象名 = 外部类对象.new 内部类( ); (经研究, 发现也可以直接用 new 来创建, 不过为了安全起见, 还是用 外部类对象.new 吧)
- Outer Class 不能直接__使用 Inner Class 的成员和方法, 要先创建__内部类对象, 然后通过这个对象来访问其成员变量和方法
- 如果外部类和内部类具有相同的成员变量或方法, 内部类默认访问自己的成员变量或方, 如果要访问外部类的成员变量, 可以使用 外部类名.this 关键字, 比如:
- 编译上面的程序后, 会发现产生了两个 .class 文件, 内部类生成的 class 文件名为 外部类名__$__内部类名
静态内部类
即用 static 修饰的内部类, 如果内部类中有静态成员, 那个这个内部类则必须也要是静态的.
- 静态内部类不能直接访问外部类的非静态成员
- 如果外部类的静态成员与内部类的成员名称不相同, 则可通过”成员名”直接调用外部类的静态成员
- 如果外部类的静态成员与内部类的成员名称相同, 可通过”类名.静态成员”访问外部类的静态成员
- 创建静态内部类的对象时, 不需要外部类的对象, 可以直接创建 **内部类 对象名= new 内部类()
// 外部类 public class HelloWorld { // 外部类中的静态变量 score private static int score = 84; // 创建静态内部类 public static class SInner { // 内部类中的变量 score int score = 91; public void show() { System.out.println("访问外部类中的score:" + HelloWorld.score); System.out.println("访问内部类中的score:" + score); } } // 测试静态内部类 public static void main(String[] args) { // 直接创建内部类的对象 SInner si = new SInner(); // 调用 show 方法 si.show(); } }
方法内部类
即, 内部类定义在外部类的方法中, 它只能在该方法内可以使用.
注意: 由于方法内部类不能在其所在方法以外的地方使用, 因此方法内部类不能使用访问控制符和 static 修饰符.
// 外部类 public class HelloWorld { private String name = "外部类"; // 外部类中的 show 方法 public void show() { // 定义方法内部类 class MInner { int score = 83; public int getScore() { return score + 10; } } // 创建方法内部类的对象 MInner ss = new MInner(); // 调用内部类的方法 int newScore = ss.getScore(); System.out.println("姓名:" + name + "\n加分后的成绩:" + newScore); } // 测试方法内部类 public static void main(String[] args) { // 创建外部类的对象 HelloWorld mo = new HelloWorld(); // 调用外部类的方法 mo.show(); } }
匿名内部类
也就是没有名字的内部类, 正因为没有名字, 所以匿名内部类只能使用一次, 它通常用来简化代码编写.
匿名内部类确切的说, 应该叫 匿名内部类对象, 它是基于 继承/实现 的:
new 接口名/父类名 { // 实现/重写 方法 }
匿名内部类对象集 继承/实现 + 重写 + 实例化 为一体.
☠