📌 内部类是什么?
定义在另一个类内部的类,可以更好地封装和代码组织。
🎯 四种内部类(一句话概括)
| 类型 | 关键字 | 一句话说明 |
|---|---|---|
| 成员内部类 | 无特殊 | 像普通成员一样,依赖外部实例 |
| 静态内部类 | static |
不依赖外部实例,常用工具类 |
| 局部内部类 | 定义在方法内 | 方法内部使用,不能有访问修饰符 |
| 匿名内部类 | 无类名 | 一次性使用,直接new接口/类 |
💡 1. 成员内部类(最常用)
java
// 外部类
class Outer {
private String outerField = "外部数据";
// 成员内部类
class Inner {
public void show() {
System.out.println("访问外部数据: " + outerField);
}
}
}
// 使用
public class Demo {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 先有外部,再有内部
inner.show();
}
}
💡 2. 静态内部类(推荐)
java
class Outer {
// 静态内部类
static class StaticInner {
public void show() {
System.out.println("我是静态内部类");
}
}
}
// 使用(不需要外部实例)
public class Demo {
public static void main(String[] args) {
Outer.StaticInner inner = new Outer.StaticInner();
inner.show();
}
}
💡 3. 局部内部类(方法内定义)
java
class Outer {
public void method() {
// 局部内部类(只能在方法内使用)
class LocalInner {
public void show() {
System.out.println("我是局部内部类");
}
}
LocalInner inner = new LocalInner();
inner.show();
}
}
💡 4. 匿名内部类(快速实现接口)
java
// 接口
interface Animal {
void makeSound();
}
public class Demo {
public static void main(String[] args) {
// 匿名内部类:直接new接口
Animal dog = new Animal() {
@Override
public void makeSound() {
System.out.println("汪汪");
}
};
dog.makeSound();
// Java 8+ 更简单的写法(Lambda)
Animal cat = () -> System.out.println("喵喵");
cat.makeSound();
}
}
🔑 关键区别速查
| 特性 | 成员内部类 | 静态内部类 | 局部内部类 | 匿名内部类 |
|---|---|---|---|---|
| 需要外部实例 | ✅ 必须 | ❌ 不需要 | ✅ 需要 | ✅ 需要 |
| 访问外部字段 | ✅ 可以 | ❌ 不能* | ✅ 可以 | ✅ 可以 |
| 定义位置 | 类中 | 类中 | 方法中 | 直接new |
| 访问修饰符 | 可以有 | 可以有 | 不能有 | 不能有 |
| 使用频率 | 经常 | 经常 | 较少 | 经常 |
*静态内部类可以通过创建外部实例来访问
🚀 快速选择指南
markdown
问:用哪种内部类?
1. 需要多次使用,且和外部类相关?
- 是 → 用成员内部类
- 否 → 继续
2. 只是工具类,不依赖外部实例?
- 是 → 用静态内部类 ✅(推荐)
- 否 → 继续
3. 只在某个方法里用?
- 是 → 用局部内部类
- 否 → 继续
4. 一次性使用,实现接口?
- 是 → 用匿名内部类
💎 实际应用场景
场景1:迭代器(成员内部类)
java
class MyList {
private String[] data = {"A", "B", "C"};
// 内部类实现迭代器
class MyIterator {
private int index = 0;
boolean hasNext() { return index < data.length; }
String next() { return data[index++]; }
}
MyIterator iterator() {
return new MyIterator();
}
}
场景2:建造者模式(静态内部类)
java
class Person {
private Person(Builder builder) { /* ... */ }
// 静态内部类作为建造者
static class Builder {
private String name;
Builder name(String name) {
this.name = name;
return this;
}
Person build() {
return new Person(this);
}
}
}
// 使用
Person p = new Person.Builder().name("张三").build();
场景3:事件监听(匿名内部类)
java
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick() {
System.out.println("按钮被点击");
}
});
⚠️ 注意事项
- 成员内部类持有外部类引用,注意内存泄漏
- 匿名内部类只能访问final局部变量
- 静态内部类不能直接访问外部实例成员
- 内部类编译后生成:
Outer$Inner.class
📝 一句话总结
成员内部类 像成员,静态内部类 像工具,局部内部类 在方法里,匿名内部类 一次用。大部分情况用静态内部类最安全!