核心思想
在匿名内部类中,this 有两个层面的含义:

- 指代当前匿名内部类的实例:当你在匿名内部类的方法中直接使用
this时,它指向的是匿名内部类自己创建的那个对象。 - 指代外部类的实例:当你在匿名内部类的方法中,通过
外部类名.this的形式来访问this时,它指向的是包含该匿名内部类的那个外部类的对象。
理解这两者的区别是掌握匿名内部类 this 的关键。
this 指代匿名内部类自身
这是最常见的情况,当你创建一个匿名内部类的实例并调用其方法时,方法内部的 this 就代表这个匿名对象。
示例代码:
public class OuterClass {
public void display() {
System.out.println("OuterClass's display() method.");
}
public void useAnonymousClass() {
// 创建一个实现 Runnable 接口的匿名内部类
Runnable r = new Runnable() {
@Override
public void run() {
// 这里的 this 指的是 new Runnable() {...} 这个匿名对象
System.out.println("Inside anonymous class. this = " + this);
System.out.println("The type of 'this' is: " + this.getClass().getName());
}
};
Thread t = new Thread(r);
t.start();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
System.out.println("In main method. outer = " + outer);
outer.useAnonymousClass();
}
}
输出结果:

In main method. outer = com.example.OuterClass@15db9742
Inside anonymous class. this = com.example.OuterClass$1@6d06d69c
The type of 'this' is: com.example.OuterClass$1
代码分析:
System.out.println("In main method. outer = " + outer);:这里的outer是OuterClass的一个实例。Runnable r = new Runnable() { ... };:我们创建了一个匿名对象,这个对象的类型是OuterClass的一个自动生成的、未命名的子类(编译器会命名为OuterClass$1)。public void run() { ... }:这是匿名内部类的方法。System.out.println("Inside anonymous class. this = " + this);:在run方法内部,this指的是当前正在执行的匿名对象,即r引用的那个对象,从输出可以看到,它的类型是com.example.OuterClass$1,而不是OuterClass。
外部类名.this 指代外部类实例
有时,匿名内部类需要访问或引用它所嵌入的外部类的实例,这时,就必须使用 外部类名.this 的形式。
示例代码:
public class OuterClass {
private String outerName = "Outer Instance";
public void displayOuterName() {
System.out.println("OuterClass's name is: " + outerName);
}
public void createAndUseAnonymous() {
// 匿名内部类需要访问外部类的 outerName 变量
// 它还需要一个方法来接收外部类的实例
new Object() { // 创建一个匿名子类
public void showOuterReference(OuterClass outer) {
// 使用 外部类名.this 来明确指代外部类的当前实例
OuterClass outerThis = OuterClass.this;
System.out.println("Anonymous class's outer reference: " + outerThis);
System.out.println("Accessing outer variable via outerThis: " + outerThis.outerName);
// 直接访问外部类的成员(如果可见)
// 因为匿名内部类是非静态的,所以可以隐式访问外部类的成员
System.out.println("Directly accessing outer variable: " + outerName);
}
}.showOuterReference(this); // 将当前外部类的实例 (this) 传递过去
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
System.out.println("In main, outer = " + outer);
outer.createAndUseAnonymous();
}
}
输出结果:
In main, outer = com.example.OuterClass@15db9742
Anonymous class's outer reference: com.example.OuterClass@15db9742
Accessing outer variable via outerThis: Outer Instance
Directly accessing outer variable: Outer Instance
代码分析:
new Object() { ... }.showOuterReference(this);:我们创建了一个匿名Object的子类,并立即调用了它的方法showOuterReference,同时将当前外部类的实例 (this) 作为参数传递。public void showOuterReference(OuterClass outer):这是匿名类的方法,它接收一个OuterClass类型的参数。OuterClass outerThis = OuterClass.this;:这是最关键的一行。OuterClass.this明确地告诉编译器:“我要获取的是OuterClass的this,而不是我这个匿名类的this”。outerThis变量现在就指向了外部类的那个实例。System.out.println("Accessing outer variable via outerThis: " + outerThis.outerName);:通过outerThis,我们成功访问了外部类的私有成员outerName。System.out.println("Directly accessing outer variable: " + outerName);:在非静态的内部类(包括匿名内部类)中,可以隐式地访问外部类的成员,所以即使不写OuterClass.this,也能直接访问outerName,但在某些情况下,比如方法参数名与外部成员名冲突,或者为了代码清晰,使用OuterClass.this是更好的选择。
常见陷阱与注意事项
在构造器中不能使用 this
匿名内部类没有显式的构造器(只有默认的),它的初始化代码块()可以看作是一个构造器,但在这个初始化块中,你不能调用 this() 或 super()。
错误示例:
new Object() {
{
// this(); // 编译错误!匿名内部类没有构造器可以调用
System.out.println("Initialization block");
}
};
this 的类型决定了可以调用的方法
由于匿名内部类是一个具体的类,它的 this 类型就是这个匿名类本身,你只能调用这个匿名类中定义的方法,或者它所实现的接口/继承的父类中的方法。
示例:
public class Outer {
public void doSomething() {
// 匿名内部类实现了 MyInterface
MyInterface obj = new MyInterface() {
@Override
public void methodA() {
System.out.println("methodA called");
// this.methodB(); // 编译错误!this 的类型是匿名类,它没有 methodB
}
};
obj.methodA();
}
public static void main(String[] args) {
new Outer().doSomething();
}
}
interface MyInterface {
void methodA();
}
匿名内部类中的 final 或 effectively final 变量
匿名内部类访问外部方法的局部变量时,该变量必须是 final 或 effectively final (即只被赋值一次),这是为了避免外部方法执行完毕后,局部变量被销毁,而匿名内部类的对象却持有一个无效的引用。
public class Outer {
public void myMethod() {
int count = 10; // effectively final
new Runnable() {
@Override
public void run() {
// System.out.println(count++); // 编译错误!不能修改 effectively final 变量
System.out.println("Count is: " + count);
}
}.run();
// count = 20; // 如果取消这行注释,上面的代码就会编译错误,因为 count 不再是 effectively final
}
}
| 上下文 | this 的含义 |
示例 | 类型 |
|---|---|---|---|
| 匿名内部类内部 | 指代匿名内部类自身的实例 | System.out.println(this); |
OuterClass$1 (编译器生成的匿名子类) |
| 匿名内部类内部 | 指代外部类的实例 | OuterClass.this |
OuterClass |
记住这个核心区别,你就能轻松应对 Java 匿名内部类中关于 this 的各种问题了。
