Java 内部类的 4 种用法(成员内部类、局部内部类、静态内部类和匿名内部类)
·
大多数情况下,Java 中的类被定义为一个独立的程序单元。但在某些情况下,也可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类(也称嵌套类),包含内部类的类也被称为外部类。
内部类包括 4 种,分别是成员内部类、局部内部类、静态内部类和匿名内部类。一般情况下,内部类有如下属性:
- 内部类和外部类由 Java 编译器编译后生成的两个类是独立的;
- 内部类是外部类的一个成员,可以使用外部类的类变量和实例变量,也可以使用外部类的局部变量;
- 内部类可以被
protected或private修饰。当一个类中嵌套另一个类时,访问保护并不妨碍内部类使用外部类的成员; - 内部类被
static修饰后,不能再使用局部范围中或其他内部类中的数据和变量。
Java 成员内部类
成员内部类是最普通的内部类,它定义于另一个类的内部,与外部类的成员变量、成员方法同级。
核心特性
- 成员内部类可以访问外部类的所有成员(包括私有成员);
- 外部类访问成员内部类需通过实例;
- 成员内部类依附外部类存在,创建成员内部类对象前必须存在外部类对象。
实例化语法
外部类名.内部类名 引用变量名 = new 外部类名().new 内部类名();
代码示例
class Outer { // 定义外部类
private String name = "外部类Outer";
private int num = 666;
class Inner { // 定义成员内部类
private String name = "内部类Inner";
public void accessOuter() {
System.out.println("在成员内部类中访问内部类的name: " + name);
System.out.println("在成员内部类中访问外部类的name: " + Outer.this.name); // Outer.this 表示外部类对象
System.out.println("在成员内部类中访问外部类的num: " + num);
}
}
}
public class Demo {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner(); // 实例化成员内部类
inner.accessOuter();
}
}
运行结果
在成员内部类中访问内部类的name: 内部类Inner
在成员内部类中访问外部类的name: 外部类Outer
在成员内部类中访问外部类的num: 666
注意事项
- 成员内部类不能定义静态变量、静态方法和静态内部类;
- 内部类与外部类成员变量重名时,需通过
Outer.this.变量名访问外部类成员。
Java 局部内部类
局部内部类是指在成员方法中定义的类,作用域仅限于该方法或代码块内。
核心特性
- 对外部类完全隐藏,仅在定义它的方法内可见;
- 不能使用访问修饰符(
public、private、protected); - 可访问外部类所有成员,但只能访问方法中
final或隐式final的局部变量(JDK 8+ 自动添加final)。
代码示例
class Outer { // 定义外部类
private static String name = "外部类Outer";
private int num = 666;
public void display() {
int count = 5; // 隐式 final(JDK 8+)
class Inner { // 局部内部类
public void accessOuter() {
System.out.println("在局部内部类中访问外部方法的变量: " + count);
System.out.println("在局部内部类中访问外部类的name: " + Outer.name);
System.out.println("在局部内部类中访问外部类的num: " + num);
}
}
new Inner().accessOuter(); // 仅在方法内可用
}
}
public class Demo {
public static void main(String[] args) {
Outer outer = new Outer();
outer.display();
}
}
运行结果
在局部内部类中访问外部方法的变量: 5
在局部内部类中访问外部类的name: 外部类Outer
在局部内部类中访问外部类的num: 666
注意事项
- 局部变量若在内部类中使用,不能修改(因隐式
final); - 局部内部类不可在外部类其他方法中使用。
Java 静态内部类
静态内部类是指用 static 关键字修饰的成员内部类,不依赖外部类实例。
核心特性
- 可直接通过外部类名实例化,无需外部类对象;
- 仅能访问外部类的静态成员(类变量、类方法);
- 可定义静态成员和非静态成员。
实例化语法
外部类名.内部类名 引用变量名 = new 外部类名.内部类名();
代码示例
class Outer {
private static String name = "外部类Outer"; // 静态成员
private static int num = 666;
static class Inner { // 静态内部类
public static String innerName = "内部类Inner"; // 静态成员
public void accessOuter() {
System.out.println("在静态内部类中访问外部类的name: " + Outer.name);
System.out.println("在静态内部类中访问外部类的num: " + num);
}
}
}
public class Demo {
public static void main(String[] args) {
// 访问静态成员
System.out.println("静态内部类静态成员: " + Outer.Inner.innerName);
// 实例化静态内部类
Outer.Inner obj = new Outer.Inner();
obj.accessOuter();
}
}
运行结果
静态内部类静态成员: 内部类Inner
在静态内部类中访问外部类的name: 外部类Outer
在静态内部类中访问外部类的num: 666
注意事项
- 静态内部类不能直接访问外部类非静态成员;
- 静态内部类独立性强,类似 “顶级类”,常用于封装工具类或数据结构(如
Map.Entry)。
Java 匿名内部类
匿名内部类是一个没有显式名字的内部类,本质是隐式继承类或实现接口的子类对象。
核心特性
- 必须继承一个类或实现一个接口;
- 无构造方法,无类名,仅能使用一次;
- 常用于事件监听、回调等一次性逻辑。
语法格式
new 类名/接口名/抽象类名() {
// 匿名内部类实现(重写方法)
}
代码示例(实现接口)
interface Inner {
void getName(String name);
}
public class Demo {
public static void main(String[] args) {
// 匿名内部类实现接口
new Inner() {
@Override
public void getName(String name) {
System.out.println("我是匿名类的方法,获取name为:" + name);
}
}.getName("张三"); // 直接调用方法
}
}
运行结果
我是匿名类的方法,获取name为:张三
注意事项
- 匿名内部类不能定义静态成员;
- 复杂逻辑(超过 4 行)建议改用具名类,避免代码臃肿。
总结对比
| 类型 | 定义位置 | 依赖外部类实例 | 访问外部成员 | 静态成员支持 | 实例化方式 |
|---|---|---|---|---|---|
| 成员内部类 | 外部类成员位置 | 是 | 所有成员 | 仅静态常量(JDK 16+) | new 外部类().new 内部类() |
| 局部内部类 | 方法 / 代码块内 | 是 | 所有成员 + 最终局部变量 | 不支持 | 仅在定义范围内实例化 |
| 静态内部类 | 外部类成员位置 | 否 | 仅静态成员 | 支持 | new 外部类.内部类() |
| 匿名内部类 | 表达式中 | 是(非静态) | 所有成员 + 最终局部变量 | 不支持 | new 父类/接口() { ... } |
更多推荐
所有评论(0)