Skip to content

内部类

静态内部类(静态变量)

静态内部类是一种定义在类内部并且用 static 修饰的类

java
public class OuterClass {
    private static String staticOuterField = "静态外部字段";
    private String instanceOuterField = "实例外部字段";

    // 静态内部类
    public static class StaticInnerClass {
        private String innerField = "内部字段";

        public void print() {
            // 可以访问外部类的静态成员
            System.out.println("访问外部静态字段: " + staticOuterField);
            
            // 不能直接访问外部类的实例字段
            // System.out.println(instanceOuterField); // 编译错误
        }
    }
}
  • 使用静态内部类就需要创建静态内部类的实例

静态内部类不依赖外部类的实例,可以直接通过外部类名访问并创建实例。

java
OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
inner.print();
  • 静态内部类可以直接访问外部类的 static 成员(字段或方法),但不能直接访问外部类的实例成员
java
public class Outer {
    // 外部类的静态成员
    private static String staticField = "外部静态字段";
    private static void staticMethod() {
        System.out.println("调用外部静态方法");
    }

    // 外部类的实例成员
    private String instanceField = "外部实例字段";
    private void instanceMethod() {
        System.out.println("调用外部实例方法");
    }

    // 静态内部类
    public static class StaticInner {
        public void testAccess() {
            // ✅ 可以访问外部类的静态字段和静态方法
            System.out.println("静态字段: " + staticField);
            staticMethod();

            // ❌ 不能直接访问外部类的实例字段和实例方法
            // System.out.println(instanceField); // 编译错误
            // instanceMethod(); // 编译错误
        }
    }

    public static void main(String[] args) {
        Outer.StaticInner inner = new Outer.StaticInner();
        inner.testAccess();
    }
}
  • 普通内部类不允许有静态成员,而静态内部类允许。
java
public static class StaticInnerClass {
    public static final String CONST = "常量";
}

实例内部类(实例变量)

实例内部类(Inner Class / 非静态内部类)定义在类内部,并且没有使用 static 修饰的类。它依赖于外部类对象存在,因此 必须先创建外部类对象,才能创建实例内部类对象

java
class Outer {

    private String name = "Outer";

    // 实例内部类
    class Inner {
        public void show() {
            System.out.println("外部类属性:" + name);
        }
    }
}
  • 实例化
java
public class Test {
    public static void main(String[] args) {

        Outer outer = new Outer();        // 创建外部类对象
        Outer.Inner inner = outer.new Inner(); // 创建内部类对象

        inner.show();
    }
}
  • 可以访问外部类的所有成员
java
class Outer {

    private int age = 18;

    class Inner {
        public void print() {
            System.out.println(age); // 可以访问private
        }
    }
}
  • 实例内部类不能定义 static 成员

实例内部类依赖外部类对象存在,而 static 成员属于类级别,不依赖对象。

局部内部类(局部变量)

局部内部类定义在方法、代码块或构造器内部的类。它的作用范围 只在所在的方法或代码块内部,离开这个作用域就无法访问。

java
class Outer {

    public void show() {

        // 局部内部类
        class Inner {
            public void print() {
                System.out.println("局部内部类");
            }
        }

        Inner inner = new Inner();
        inner.print();
    }
}

局部内部类 可以访问方法中的局部变量,但必须是 final

java
class Outer {

    public Runnable getRunnable() {

        int num = 10;

        class Inner implements Runnable {
            public void run() {
                System.out.println(num);
            }
        }

        return new Inner();
    }
}
java
Outer outer = new Outer();
Runnable r = outer.getRunnable();

r.run();
调用 getRunnable()

创建 Inner 对象(在堆中)

方法结束

栈变量 num 消失

Inner 对象仍然存在

Inner 对象仍然存在,虽然仍然能够访问num,但是访问的是num的副本,因此num只有是final的才能保证程序是正确的

实际上局部内部类使用的局部变量,就算你没有加final,也会被编译器加上final

匿名内部类

匿名内部类没有类名的内部类,通常用于 只需要创建一次对象的场景。它本质上是 局部内部类的简化写法

java
public class Test {

    public static void main(String[] args) {

        Computer computer = new Computer();

        computer.useUSB(new USB() {

            @Override
            public void open() {
                System.out.println("U盘连接");
            }

            @Override
            public void close() {
                System.out.println("U盘拔出");
            }
        });

    }
}
java
class Computer {

    public void useUSB(USB usb) {

        usb.open();
        System.out.println("设备正在使用...");
        usb.close();
    }
}
  • new 接口 {}表示去实现一个接口,创建的对象直接传入形参,没有名字。

  • 匿名内部类支持创建接口和父类的子类实例

  • 这个实现类只在此使用一次,因此无需创建一个单独的文件。