成员内部类
当一个类只为另一个类服务,且需要频繁访问外部类的私有成员时,成员内部类是最自然的选择。
基本定义
定义在外部类的成员位置(不是方法内):
java
public class Outer {
private String outerField = "外部类私有字段";
// 成员内部类
public class Inner {
private String innerField = "内部类字段";
public void display() {
// ✅ 可以直接访问外部类的私有成员
System.out.println(outerField);
System.out.println(innerField);
}
}
}创建方式
java
public class InnerCreationDemo {
public static void main(String[] args) {
// 方式一:分步创建
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
// 方式二:一步完成
Outer.Inner inner2 = new Outer().new Inner();
inner.display();
}
}访问权限控制
成员内部类本身也可以用访问修饰符:
java
public class Outer {
public class InnerPublic { } // 任何地方可访问内部类
protected class InnerProtected { } // 子类和同包可访问
private class InnerPrivate { } // 只有外部类可访问
class InnerDefault { } // 同包可访问
}外部类的私有内部类是一种真正的封装——即使其他类拿到了外部类实例,也无法访问 private 内部类。
访问外部类成员
非静态内部类天然持有外部类引用,通过 OuterClass.this 访问:
java
public class Outer {
private int value = 10;
public class Inner {
private int value = 20;
public void display() {
System.out.println("Inner value: " + this.value); // 20
System.out.println("Outer value: " + Outer.this.value); // 10
}
}
}与外部类实例绑定
关键点:成员内部类依附于外部类实例存在。创建内部类之前,必须先有外部类实例:
java
public class BindingDemo {
public static void main(String[] args) {
Outer outer = new Outer();
// ✅ 可以创建多个内部类实例,共享同一个外部类
Outer.Inner inner1 = outer.new Inner();
Outer.Inner inner2 = outer.new Inner();
// 不同外部类实例的内部类是独立的
Outer anotherOuter = new Outer();
Outer.Inner inner3 = anotherOuter.new Inner();
}
}实际应用:迭代器模式
java
public class Container {
private Object[] elements = {1, 2, 3};
// 成员内部类:迭代器
public class Iterator {
private int index = 0;
public boolean hasNext() {
return index < elements.length;
}
public Object next() {
return elements[index++];
}
}
public Iterator getIterator() {
return new Iterator();
}
public static void main(String[] args) {
Container container = new Container();
Container.Iterator iter = container.getIterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}注意事项
- 持有外部引用:非静态内部类对象持有指向外部类对象的引用
- 可访问私有成员:可以访问外部类的所有成员(包括 private)
- 依附实例:创建前必须先有外部类实例
- 命名冲突:可用
OuterClass.this明确指定访问外部类成员
