Appearance
🔐 内部类与匿名类
内部类概述
内部类(Inner Class)是定义在另一个类内部的类。Java 提供了多种类型的内部类:
- 成员内部类(Member Inner Class)
- 静态内部类(Static Nested Class)
- 局部内部类(Local Inner Class)
- 匿名内部类(Anonymous Inner Class)
成员内部类
基本语法
java
public class Outer {
private String outerField = "外部类字段";
// 成员内部类
public class Inner {
private String innerField = "内部类字段";
public void display() {
System.out.println("外部类字段: " + outerField); // 可以访问外部类成员
System.out.println("内部类字段: " + innerField);
}
}
// 创建内部类对象
public void createInner() {
Inner inner = new Inner();
inner.display();
}
}使用成员内部类
java
// 创建内部类对象
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 通过外部类对象创建
inner.display();
// 或者
Outer.Inner inner2 = new Outer().new Inner();访问外部类成员
java
public class Outer {
private int outerVar = 10;
public class Inner {
private int innerVar = 20;
public void method() {
// 访问外部类成员
System.out.println("外部类变量: " + outerVar);
System.out.println("外部类变量: " + Outer.this.outerVar); // 明确指定
// 访问内部类成员
System.out.println("内部类变量: " + innerVar);
System.out.println("内部类变量: " + this.innerVar);
}
}
}静态内部类
基本语法
java
public class Outer {
private static String staticField = "静态字段";
private String instanceField = "实例字段";
// 静态内部类
public static class StaticInner {
public void display() {
System.out.println("静态字段: " + staticField); // 只能访问静态成员
// System.out.println(instanceField); // ❌ 错误:不能访问实例成员
}
public static void staticMethod() {
System.out.println("静态内部类的静态方法");
}
}
}使用静态内部类
java
// 不需要外部类对象,直接创建
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.display();
// 调用静态方法
Outer.StaticInner.staticMethod();局部内部类
基本语法
java
public class Outer {
private String outerField = "外部类字段";
public void method() {
final String localVar = "局部变量"; // 必须是 final 或 effectively final
// 局部内部类
class LocalInner {
public void display() {
System.out.println("外部类字段: " + outerField);
System.out.println("局部变量: " + localVar);
}
}
// 在方法内使用
LocalInner localInner = new LocalInner();
localInner.display();
}
}局部内部类的限制
java
public class Outer {
public void method() {
// 局部内部类不能有访问修饰符
class LocalInner {
// ❌ public class LocalInner { } // 错误
// 局部内部类不能有静态成员(Java 16+ 允许)
// static int staticVar = 10; // Java 16 之前错误
}
}
}匿名内部类
基本语法
java
// 实现接口
interface Greeting {
void greet(String name);
}
public class Outer {
public void method() {
// 匿名内部类
Greeting greeting = new Greeting() {
@Override
public void greet(String name) {
System.out.println("Hello, " + name);
}
};
greeting.greet("张三");
}
}继承类的匿名内部类
java
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
public class Outer {
public void method() {
// 匿名内部类继承 Animal
Animal animal = new Animal() {
@Override
public void makeSound() {
System.out.println("匿名动物发出声音");
}
};
animal.makeSound();
}
}Lambda 表达式(Java 8+)
java
// 函数式接口
interface Calculator {
int calculate(int a, int b);
}
public class Outer {
public void method() {
// 使用匿名内部类
Calculator calc1 = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// 使用 Lambda 表达式(更简洁)
Calculator calc2 = (a, b) -> a + b;
System.out.println(calc1.calculate(5, 3)); // 8
System.out.println(calc2.calculate(5, 3)); // 8
}
}内部类的应用场景
1. 事件处理
java
public class Button {
private String text;
private OnClickListener listener;
public interface OnClickListener {
void onClick();
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick();
}
}
}
// 使用
Button button = new Button();
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick() {
System.out.println("按钮被点击");
}
});2. 迭代器实现
java
public class MyList {
private String[] items = {"a", "b", "c"};
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < items.length;
}
@Override
public String next() {
return items[index++];
}
};
}
}3. 辅助类封装
java
public class Outer {
private String data;
// 使用静态内部类封装相关的辅助类
public static class Builder {
private String data;
public Builder setData(String data) {
this.data = data;
return this;
}
public Outer build() {
Outer outer = new Outer();
outer.data = this.data;
return outer;
}
}
}
// 使用
Outer outer = new Outer.Builder()
.setData("数据")
.build();内部类的优势
1. 访问控制
java
public class Outer {
private String privateField = "私有字段";
// 内部类可以访问外部类的私有成员
public class Inner {
public void accessPrivate() {
System.out.println(privateField); // ✅ 可以访问
}
}
}2. 代码组织
java
// 将相关的类组织在一起
public class LinkedList {
// 节点类作为内部类更合理
private static class Node {
Object data;
Node next;
Node(Object data) {
this.data = data;
}
}
private Node head;
}3. 实现回调
java
public class EventHandler {
public void handleEvent(Event event) {
// 使用匿名内部类实现回调
event.setOnComplete(new Callback() {
@Override
public void onComplete() {
System.out.println("事件完成");
}
});
}
}完整示例
java
// 外部类
public class Outer {
private String outerField = "外部类字段";
private static String staticField = "静态字段";
// 成员内部类
public class MemberInner {
public void display() {
System.out.println("成员内部类访问: " + outerField);
}
}
// 静态内部类
public static class StaticInner {
public void display() {
System.out.println("静态内部类访问: " + staticField);
}
}
// 方法中使用局部内部类
public void methodWithLocalInner() {
final String localVar = "局部变量";
class LocalInner {
public void display() {
System.out.println("局部内部类访问: " + outerField);
System.out.println("局部变量: " + localVar);
}
}
LocalInner localInner = new LocalInner();
localInner.display();
}
// 方法中使用匿名内部类
public void methodWithAnonymous() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类执行");
}
};
new Thread(runnable).start();
}
}
// 使用示例
public class InnerClassExample {
public static void main(String[] args) {
Outer outer = new Outer();
// 成员内部类
Outer.MemberInner memberInner = outer.new MemberInner();
memberInner.display();
// 静态内部类
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.display();
// 局部内部类
outer.methodWithLocalInner();
// 匿名内部类
outer.methodWithAnonymous();
}
}注意事项
1. 成员内部类不能有静态成员(Java 16+ 允许)
java
public class Outer {
public class Inner {
// ❌ Java 16 之前错误
// static int staticVar = 10;
// ✅ Java 16+ 允许
static int staticVar = 10;
}
}2. 局部变量必须是 final 或 effectively final
java
public void method() {
final String finalVar = "final"; // ✅ 可以
String effectivelyFinal = "effectively final"; // ✅ 可以(只赋值一次)
// String notFinal = "not final"; // ❌ 错误(如果多次赋值)
class LocalInner {
public void display() {
System.out.println(finalVar); // ✅ 可以
System.out.println(effectivelyFinal); // ✅ 可以
}
}
}3. 内部类与外部类的 this
java
public class Outer {
private String name = "Outer";
public class Inner {
private String name = "Inner";
public void display() {
System.out.println(this.name); // Inner
System.out.println(Outer.this.name); // Outer
}
}
}最佳实践
1. 优先使用静态内部类
java
// ✅ 如果不访问外部类实例成员,使用静态内部类
public class Outer {
public static class StaticInner {
// 不依赖外部类实例
}
}
// ❌ 如果不必要,避免使用成员内部类(需要外部类实例)2. 使用 Lambda 替代匿名内部类
java
// ✅ Java 8+ 使用 Lambda
Runnable r = () -> System.out.println("Hello");
// ❌ 不使用匿名内部类(如果可以用 Lambda)
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};3. 合理使用内部类
java
// ✅ 内部类用于封装相关功能
public class LinkedList {
private static class Node {
// 节点类只与链表相关
}
}
// ❌ 避免过度嵌套下一步
掌握了内部类与匿名类后,可以继续学习:
💡 提示:内部类和匿名类提供了代码组织和功能封装的有力工具,但要合理使用,避免过度复杂
