Java 内部类详解:成员内部类、静态内部类、局部内部类与匿名内部类

在 Java 中,内部类是指定义在另一个类内部的类。根据定义的位置和方式不同,内部类可以分为:成员内部类静态内部类局部内部类匿名内部类。本文将对这四种内部类进行详细讲解,并给出代码示例和使用场景。

一、什么是内部类?

内部类 就是写在一个类里面的类。

它的主要作用是增强封装性,让某个类仅在外部类的范围内使用,或者表示一种"所属关系"。


二、什么时候使用内部类?

当一个类所表示的事物是另一个类的一部分,且单独存在没有意义时,适合使用内部类。

例如:

  • 汽车的发动机

  • 人的心脏


三、成员内部类(了解)

定义位置:成员位置(与属性、方法同级),属于外部类的成员。

特点:

  • 可以被 privatedefaultprotectedpublicstatic 等修饰符修饰。

  • 在 JDK 16 之前,成员内部类中不能定义静态变量;JDK 16 开始可以定义静态变量。

示例代码:

java 复制代码
public class Car {
    String carName;
    int carAge;
    int carColor;

    class Engine { // 成员内部类
        String engineName;
        int engineAge;
    }
}

获取成员内部类对象的方式:

方式一:外部类提供方法返回内部类对象。

java 复制代码
public class Car {
    String carName;
    int carAge;
    int carColor;
    
    // 成员内部类
    class Engine {
        String engineName;
        int engineAge;
        
        public void show() {
            System.out.println("发动机名称:" + engineName);
            System.out.println("发动机年龄:" + engineAge);
        }
    }
    
    // 方式一:外部类提供方法返回内部类对象
    public Engine getEngine() {
        return new Engine();
    }
    
    
}

// 使用示例
public class Test {
    public static void main(String[] args) {
        // 方式一:通过外部类的方法获取内部类对象
        Car car = new Car();
        
        // 直接获取
        Car.Engine engine1 = car.getEngine();
    }
}

方式二:直接创建。

java 复制代码
Outer.Inner oi = new Outer().new Inner();

变量访问规则:

当内部类与外部类存在同名变量时,可以通过 this外部类名.this 区分:

java 复制代码
public class Outer {
    private int a = 10;

    class Inner {
        private int a = 20;

        public void show() {
            int a = 30;
            System.out.println(a);              // 30
            System.out.println(this.a);         // 20
            System.out.println(Outer.this.a);   // 10
        }
    }
}

四、静态内部类

定义位置 :成员位置,使用 static 修饰。

特点:

  • 只能直接访问外部类中的静态变量和静态方法

  • 若想访问外部类的非静态成员,必须创建外部类的对象

  • 静态内部类本身可以包含静态成员和非静态成员

  • 不需要外部类对象就可以创建静态内部类的对象

示例代码:

java 复制代码
public class Car {
    // 外部类的成员变量
    String carName = "宝马";           // 非静态变量
    static String brand = "BMW";      // 静态变量
    int carAge = 2;                   // 非静态变量
    
    // 外部类的成员方法
    public void start() {
        System.out.println("汽车启动");
    }
    
    public static void staticMethod() {
        System.out.println("外部类的静态方法");
    }
    
    // 静态内部类
    static class Engine {
        String engineName = "V8发动机";     // 非静态变量
        static int engineCount = 4;         // 静态变量
        
        public void show() {
            // 1. 可以直接访问外部类的静态成员
            System.out.println("外部类的静态变量: " + brand);
            staticMethod();  // 可以直接调用外部类的静态方法
            
            // 2. 不能直接访问外部类的非静态成员
            // System.out.println(carName);  // 编译错误!
            // start();  // 编译错误!
            
            // 3. 访问外部类非静态成员需要创建外部类对象
            Car car = new Car();
            System.out.println("外部类的非静态变量: " + car.carName);
            car.start();
            
            // 4. 访问自己的成员
            System.out.println("发动机名称: " + engineName);
            System.out.println("发动机数量: " + engineCount);
        }
        
        public static void staticShow() {
            // 静态方法中只能直接访问外部类的静态成员
            System.out.println("外部类的静态变量: " + brand);
            
            // 不能直接访问自己的非静态成员
            // System.out.println(engineName);  // 编译错误!
            
            // 需要创建对象才能访问非静态成员
            Engine engine = new Engine();
            System.out.println("发动机名称: " + engine.engineName);
        }
    }
}

五、局部内部类

定义位置:方法内部。

特点:

  • 类似于局部变量,外界无法直接使用。

  • 必须在方法内部创建对象并使用。

  • 可以直接访问外部类的成员,也可以访问方法内的局部变量。

示例代码:

java 复制代码
public class Outer {
    public void method() {
        class LocalInner {
            public void show() {
                System.out.println("局部内部类");
            }
        }
        LocalInner li = new LocalInner();
        li.show();
    }
}

六、匿名内部类

定义位置:成员位置或局部位置。

特点:

  • 没有名字的内部类。

  • 本质是:一个没有名字的 Java 类 + 实现接口/继承类 + 重写方法 + 创建对象。

  • 常用于只需要使用一次的类实现,简化代码。

格式:

java 复制代码
new 类名或接口名() {
    重写方法;
};

示例代码:

java 复制代码
Inter inter = new Inter() {
    public void show() {
        System.out.println("匿名内部类实现");
    }
};

使用场景:

  • 实现接口或继承类,且该类只使用一次。

  • 是 Lambda 表达式的前置知识点。

相关推荐
朦胧之9 小时前
AI 编程-老项目改造篇
java·前端·后端
程序猿大帅13 小时前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
程序员晓琪14 小时前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly14 小时前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
众少成多积小致巨15 小时前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
东坡白菜15 小时前
破局全栈:前端开发的Java入门实战记录—JPA(2)
java·后端
SimonKing21 小时前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
用户2986985301421 小时前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
小bo波2 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
nanxun8863 天前
记一次诡异的 Docker 容器"串包"故障排查
java