核心思想
内部类之所以能访问外部类的成员(包括方法和变量),是因为内部类持有了一个指向外部类对象的隐式引用,当你创建一个内部类对象时,JVM 会自动将外部类的对象引用传递给内部类。

这个隐式引用在 Java 代码中的体现形式是:外部类名.this。
内部类调用外部类的实例方法
这是最常见的情况,内部类可以直接访问外部类的所有 public、protected、default(包私有)和 private 的实例方法和实例变量。
代码示例
public class OuterClass {
private String outerName = "外部类实例变量";
private void outerPrivateMethod() {
System.out.println("这是外部类的私有方法 (outerPrivateMethod)");
}
// 定义一个成员内部类
class InnerClass {
public void innerMethod() {
System.out.println("--- 内部类方法开始调用外部类方法 ---");
// 1. 直接访问外部类的实例变量
System.out.println("访问外部类的实例变量: " + outerName);
// 2. 直接调用外部类的私有方法
outerPrivateMethod();
// 3. 如果需要,也可以显式地使用 "外部类名.this" 来引用外部类对象
// OuterClass.this 就代表当前这个 InnerClass 所在的 OuterClass 对象
System.out.println("显式引用外部类对象: " + OuterClass.this);
System.out.println("显式引用外部类实例变量: " + OuterClass.this.outerName);
OuterClass.this.outerPrivateMethod();
System.out.println("--- 内部类方法调用结束 ---");
}
}
// 外部类的方法,用于创建内部类对象并调用其方法
public void useInnerClass() {
// 创建内部类对象
InnerClass inner = new InnerClass();
// 调用内部类的方法
inner.innerMethod();
}
}
测试代码
public class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.useInnerClass();
}
}
输出结果
--- 内部类方法开始调用外部类方法 ---
访问外部类的实例变量: 外部类实例变量
这是外部类的私有方法
显式引用外部类对象: OuterClass@15db9742
显式引用外部类的实例变量: 外部类实例变量
这是外部类的私有方法
--- 内部类方法调用结束 ---
关键点分析:
- 直接访问:在
InnerClass的innerMethod中,我们可以像访问自己的成员一样直接使用outerName和outerPrivateMethod()。 - 显式引用
OuterClass.this:OuterClass.this是一个完整的表达式,它指向创建该内部类对象的外部类实例,在大多数情况下,编译器会自动帮你处理,所以不需要显式写出,但在某些情况下(内部类的成员变量与外部类的成员变量同名时),就必须使用它来消除歧义。
处理成员变量名冲突的情况
当内部类的成员变量(或方法)与外部类的成员变量(或方法)同名时,会产生“隐藏”现象,如果想在内部类中访问外部类的被隐藏成员,就必须使用 外部类名.this。

代码示例
public class OuterClass {
// 外部类有一个名为 name 的变量
private String name = "外部类的 name";
class InnerClass {
// 内部类也有一个名为 name 的变量
private String name = "内部类的 name";
public void printNames() {
System.out.println("内部类的 name: " + name); // 直接访问,访问的是内部自己的
System.out.println("外部类的 name: " + OuterClass.this.name); // 必须使用 this 来访问外部类的
}
}
}
测试代码
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
静态内部类 调用外部类方法
静态内部类不持有外部类的隐式引用,它不能直接访问外部类的实例成员(实例变量和实例方法)。
它只能访问:
- 外部类的
static成员。 - 外部类的
public成员(如果外部类本身是public的)。
如果确实需要访问外部类的实例成员,必须通过一个外部类的对象来调用。
代码示例
public class OuterClass {
private String outerInstanceVar = "外部类实例变量";
private static String outerStaticVar = "外部类静态变量";
// 静态内部类
static class StaticInnerClass {
public void accessMembers() {
System.out.println("--- 静态内部类方法 ---");
// 1. 可以直接访问外部类的静态成员
System.out.println("访问外部类静态变量: " + outerStaticVar);
// 2. 不能直接访问外部类的实例成员,编译会报错
// System.out.println(outerInstanceVar); // Compile Error!
// 3. 必须通过外部类的对象来访问实例成员
OuterClass outerObj = new OuterClass();
System.out.println("通过外部类对象访问实例变量: " + outerObj.outerInstanceVar);
outerObj.outerInstanceMethod();
}
}
private void outerInstanceMethod() {
System.out.println("这是外部类的实例方法");
}
}
测试代码
public class Main {
public static void main(String[] args) {
// 创建静态内部类对象,不需要先创建外部类对象
OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
staticInner.accessMembers();
}
}
输出结果
--- 静态内部类方法 ---
访问外部类静态变量: 外部类静态变量
通过外部类对象访问实例变量: 外部类实例变量
这是外部类的实例方法
局部内部类 和 匿名内部类
这两种内部类也遵循与成员内部类相同的规则,因为它们都是非静态的,所以都持有对外部类对象的引用,它们可以访问外部类的所有成员,以及其所在作用域中的 final 或等效 final 的局部变量。

匿名内部类示例
public class OuterClass {
public void show() {
System.out.println("外部类的 show() 方法");
}
public void createAnonymousInner() {
// 创建一个匿名内部类,它实现了 Runnable 接口
// 这个匿名内部类可以访问外部类的成员
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("--- 匿名内部类的 run() 方法 ---");
// 调用外部类的 show() 方法
OuterClass.this.show(); // 显式调用,也可以省略 this
System.out.println("访问外部类的成员");
}
};
new Thread(r).start();
}
}
| 内部类类型 | 是否持有外部类引用? | 能否直接访问外部类实例成员? | 如何访问外部类实例成员? |
|---|---|---|---|
| 成员内部类 | 是 | 能 | 直接访问,或使用 外部类名.this |
| 静态内部类 | 否 | 不能 | 必须创建外部类的对象,然后通过对象访问 |
| 局部内部类 | 是 | 能 | 直接访问,或使用 外部类名.this |
| 匿名内部类 | 是 | 能 | 直接访问,或使用 外部类名.this |
记住这个核心区别:静态内部类没有外部类引用,其他内部类都有,这是理解它们如何与外部类交互的关键。
