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 表达式的前置知识点。

相关推荐
于先生吖2 小时前
国际语言适配拼车系统 JAVA 后端源码 + 同城顺风车功能全解析
java·开发语言
czlczl200209252 小时前
KRaft原理
java·zookeeper
毕设源码-朱学姐3 小时前
【开题答辩全过程】以 基于SSM的宜佳家具电商平台为例,包含答辩的问题和答案
java
客卿1233 小时前
最小生成树(贪心)--构造回文串(字符串 + 回文判断 + 构造)
java·开发语言·算法
天启HTTP3 小时前
多线程环境下,动态IP怎么分配最合理
java·服务器·网络
hzb666663 小时前
xd_day32-day40
java·javascript·学习·安全·web安全·tomcat·php
东北甜妹3 小时前
Python脚本
java·开发语言·前端
心勤则明3 小时前
Spring AI Alibaba 实战 MCP 协议
java·人工智能·spring
NGC_66113 小时前
ConcurrentHashMap1.8 多线程扩容机制
java·开发语言