这是一个非常核心且重要的 Java 特性。内部类天生就持有外部类的一个引用,因此它可以无障碍地访问外部类的所有成员,无论这些成员是 public、protected、default(包私有)还是 private 的。

核心原理:隐式的外部类引用
当你编译一个包含内部类的 Java 文件时,编译器会做两件事:
- 为外部类生成一个
.class文件,OuterClass.class。 - 为内部类生成一个
.class文件,文件名格式为OuterClass$InnerClass.class。
关键在于,编译器在生成的 OuterClass$InnerClass.class 文件中,自动添加了一个指向外部类对象的引用,这个引用通常有一个特殊的名字,this$0。
这个隐式引用使得内部类的方法在执行时,总是知道它属于哪个外部类对象,从而可以访问该外部类对象的成员。
访问规则详解
内部类访问外部类成员时,遵循以下规则:

a. 访问外部类的实例成员(非 static 成员)
这是最常见的情况,内部类可以直接访问外部类的实例方法和实例字段。
示例代码:
class OuterClass {
// 外部类的私有实例字段
private String outerInstanceField = "这是外部类的实例字段";
// 外部类的实例方法
public void outerInstanceMethod() {
System.out.println("外部类的实例方法被调用了");
}
// 定义一个内部类
class InnerClass {
public void accessOuterMembers() {
// 1. 直接访问外部类的私有实例字段
System.out.println("内部类访问外部类的实例字段: " + outerInstanceField);
// 2. 直接调用外部类的实例方法
outerInstanceMethod();
}
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 1. 创建外部类对象
OuterClass outer = new OuterClass();
// 2. 通过外部类对象创建内部类对象
// 语法: OuterClass.InnerClass inner = outer.new InnerClass();
OuterClass.InnerClass inner = outer.new InnerClass();
// 3. 调用内部类的方法,该方法会访问外部类的成员
inner.accessOuterMembers();
}
}
输出结果:
内部类访问外部类的实例字段: 这是外部类的实例字段
外部类的实例方法被调用了
关键点:

- 创建内部类对象的前提是必须先存在一个外部类对象,语法是
outer.new InnerClass()。 - 内部类对象
inner持有对外部类对象outer的引用,因此可以访问其所有成员。
b. 访问外部类的静态成员(static 成员)
内部类不仅可以访问外部类的实例成员,也可以访问外部类的静态成员(静态字段和静态方法)。
示例代码:
class OuterClass {
// 外部类的静态字段
private static String outerStaticField = "这是外部类的静态字段";
// 外部类的静态方法
public static void outerStaticMethod() {
System.out.println("外部类的静态方法被调用了");
}
class InnerClass {
public void accessOuterStaticMembers() {
// 1. 直接访问外部类的静态字段
System.out.println("内部类访问外部类的静态字段: " + outerStaticField);
// 2. 直接调用外部类的静态方法
outerStaticMethod();
}
}
}
// 测试类
public class Main {
public static void main(String[] args) {
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
inner.accessOuterStaticMembers();
}
}
输出结果:
内部类访问外部类的静态字段: 这是外部类的静态字段
外部类的静态方法被调用了
特殊情况:静态内部类
静态内部类(用 static 修饰的内部类)是一个特例,它本质上是一个外部类的静态成员,而不是一个外部类对象的“内部”部分。
静态内部类不持有外部类的隐式引用,这意味着:
- 它不能访问外部类的实例成员(非
static字段和方法)。 - 它可以访问外部类的静态成员(
static字段和方法)。 - 创建静态内部类对象时,不需要先创建外部类对象,语法是
new OuterClass.InnerClass()。
示例代码:
class OuterClass {
private String outerInstanceField = "外部类的实例字段"; // 实例成员
private static String outerStaticField = "外部类的静态字段"; // 静态成员
// 定义一个静态内部类
static class StaticInnerClass {
public void accessMembers() {
// 下面这行代码会编译出错!
// System.out.println(outerInstanceField); // Error: 无法从静态上下文中引用非静态 变量 outerInstanceField
// 下面这行代码是正确的
System.out.println("静态内部类访问外部类的静态字段: " + outerStaticField);
}
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 创建静态内部类对象,不需要外部类对象
OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
staticInner.accessMembers();
}
}
当内部类和外部类有同名成员时
如果内部类和外部类拥有同名的字段或方法,内部类默认会访问自己的成员,如果想在内部类中明确访问外部类的成员,可以使用 外部类类名.this 的形式。
示例代码:
class OuterClass {
private String name = "外部类的 name";
class InnerClass {
private String name = "内部类的 name";
public void printNames() {
// 访问内部类的 name
System.out.println("内部类的 name: " + this.name);
// 访问外部类的 name
System.out.println("外部类的 name: " + OuterClass.this.name);
}
}
}
// 测试类
public class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.printNames();
}
}
输出结果:
内部类的 name: 内部类的 name
外部类的 name: 外部类的 name
局部内部类和匿名内部类
这两种内部类也遵循相同的规则,因为它们本质上也是内部类,只是定义的位置和形式不同。
- 局部内部类:定义在方法或作用域内部,它可以访问外部类的所有成员,以及方法中
final或有效final的局部变量。 - 匿名内部类:没有类名,常用于实现接口或继承类,它同样可以访问外部类的所有成员。
匿名内部类示例:
interface Greeting {
void sayHello();
}
class Outer {
private String message = "你好,世界!";
public Greeting getGreeting() {
// 匿名内部类
return new Greeting() {
@Override
public void sayHello() {
// 可以访问外部类的私有成员 message
System.out.println(message);
}
};
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Greeting greeting = outer.getGreeting();
greeting.sayHello(); // 输出: 你好,世界!
}
}
| 内部类类型 | 是否持有外部类引用 | 能否访问外部类实例成员 | 能否访问外部类静态成员 | 创建方式 |
|---|---|---|---|---|
| 成员内部类 | 是 | 是 | 是 | outer.new InnerClass() |
| 静态内部类 | 否 | 否 | 是 | new OuterClass.InnerClass() |
| 局部内部类 | 是 | 是 | 是 | 在其定义的作用域内 new InnerClass() |
| 匿名内部类 | 是 | 是 | 是 | new Interface() { ... } |
核心要点记住:非静态的内部类都持有一个对外部类对象的隐式引用,因此可以自由访问外部类的所有成员。 静态内部类是唯一的例外。
