14. 内部类
一、内部类概述
1. 定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类
2. 内部类提供了更好的封装,它隐藏在外部类之内,不允许同一个包中的其他类访问该类
3. 内部类作为外部类的成员,可以直接访问外部类的私有数据,但外部类不能访问内部类的实现细节
4. 内部类比外部类可以多使用三个修饰符:private、protected、static
5. 定义在方法中的内部类被称为局部内部类,定义在外部类中其他位置的内部类被称为成员内部类
- 成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员,而局部内部类和匿名内部类则不是类成员
6. 大部分时候,内部类都被作为成员内部类定义,成员内部类分为两种:非静态内部类、静态内部类,后者需使用static修饰
二、非静态内部类
// 外部类Cow:奶牛 public class Cow { private double weight; public Cow() {} public Cow(double weight) { this.weight = weight; } // 定义一个非静态内部类CowLeg:牛腿 private class CowLeg { private double length; private String color; public CowLeg() {} public CowLeg(double length, String color) { this.length = length; this.color = color; } // 非静态内部类的实例方法 public void info() { System.out.println("当前牛腿颜色是:" + color + ", 高:" + length); // 直接访问外部类的私有成员变量weight System.out.println("本牛腿所属的奶牛重:" + weight); } } public void test() { // 在外部类里使用非静态内部类,与使用普通类没有太大区别 CowLeg cl = new CowLeg(1.12, "黑白相间"); cl.info(); } public static void main(String[] args) { Cow cow = new Cow(378.5); cow.test(); } }
1. 非静态内部类不能拥有静态成员,即非静态内部类里不能有静态成员变量、静态方法、静态初始化块
2. 由于静态成员不能访问非静态成员,故不允许在外部类的静态成员中直接使用非静态内部类
3. 非静态内部类的成员可以直接访问外部类的private成员,因为内部类被当成其外部类的成员
4. 如果外部类需要访问非静态内部类的实例成员,则必须显式创建非静态内部类对象来调用访问其实例成员
public class Outer { class Inner { private int inProp = 5; } // 错误示范:外部类不能直接访问非静态内部类的实例成员 System.out.println("内部类的inProp值:" + inProp); // 正确示范:显式创建内部类对象,由其调用内部类实例成员 System.out.println("内部类的inProp值:" + new Inner().inProp); }
4. 如果外部类成员变量、内部类成员变量以及内部类里方法的局部变量同名,则可通过使用外部类类名.this、this作为限定来区分
- 通过外部类类名.this.varName访问外部类实例变量,通过this.varName访问内部类实例变量
三、静态内部类
1. 静态内部类属于外部类本身,而不属于外部类的某个对象
2. 静态内部类既可以包含静态成员,也可以包含非静态成员
3. 由于静态内部类是外部类的一个静态成员,故允许在外部类的所有成员中直接使用静态内部类
4. 由于静态成员不能访问非静态成员,故静态内部类不能访问外部类的实例成员,只能访问外部类的类成员
5. 如果外部类需要访问静态内部类的成员,则必须使用静态内部类类名/对象作为调用者来访问静态内部类的类成员/实例成员
四、使用内部类