Java 内部类
内部类(Inner Class)是定义在另一个类内部的类。它能把"只服务于外部类"的逻辑就近封装,还能直接访问外部类的私有成员,常用于事件监听、迭代器、回调等场景。
什么是内部类
内部类天然"绑定"着外部类的一个对象,因此可以直接读写外部类的字段(包括 private),无需额外传参:
class Outer {
private int x = 10;
class Inner { // 成员内部类(非静态)
void show() {
System.out.println("x = " + x); // 直接访问外部私有成员
}
}
}
// —— 片段需放进 main 方法中运行 ——
Outer o = new Outer();
Outer.Inner in = o.new Inner(); // 必须借助外部类对象创建
in.show();
// 输出:x = 10
静态内部类
用 static 修饰的内部类不依赖外部类对象,相当于独立类,但只能访问外部类的静态成员:
class Outer {
static int y = 5;
static class StaticInner { // 静态内部类
void show() { System.out.println("y = " + y); }
}
}
// —— 片段需放进 main 方法中运行 ——
Outer.StaticInner si = new Outer.StaticInner();
si.show();
// 输出:y = 5
局部内部类
定义在方法内部的类叫局部内部类,作用域只限于该方法,方法结束即失效:
class Outer {
void test() {
class Local { // 局部内部类
void hello() { System.out.println("局部内部类"); }
}
new Local().hello();
}
}
// —— 片段需放进 main 方法中运行 ——
new Outer().test();
// 输出:局部内部类
匿名内部类
匿名内部类没有类名,在 new 接口或抽象类的同时直接给出实现,适合"只用一次"的逻辑:
interface Greet { void say(); }
// —— 片段需放进 main 方法中运行 ——
Greet g = new Greet() { // 匿名内部类:new 接口 + 实现体
@Override public void say() {
System.out.println("你好");
}
};
g.say();
// 输出:你好
匿名内部类要点:语法是 new 接口/抽象类() { 实现 };只能创建一个对象;常在事件监听、线程、回调里代替写一个正式类。
lambda 简化匿名内部类
如果接口只有一个抽象方法(函数式接口),JDK8 可以用 lambda 一行替代上面的匿名内部类:
Greet g2 = () -> System.out.println("你好"); // lambda 写法
g2.say();
// 输出:你好
字节码文件名
内部类编译后会各自生成独立的 .class 文件:成员内部类叫 Outer$Inner.class,匿名内部类按出现顺序叫 Outer$1.class、Outer$2.class,局部内部类如 Outer$1Local.class。
内部类把"紧密协作的类"收拢在一起,能方便地访问外部私有成员;匿名内部类尤其擅长快速实现接口,配合 lambda 让代码更加简洁。