当前位置: 首页 > news >正文

内部类详解:Java中的嵌套艺术

一、什么是内部类?

        顾名思义,它是一个类的内部定义的另一个类。

        这是 java 语言中一个独特而强大的特性

        就像现实生活中,房子包含房间一样

        主要包含四大类:

        成员内部类、静态内部类、局部内部类、匿名内部类

二、内部类的历史背景及意义

        现在我们大致了解了什么是内部类

        但是为什么要有内部类这个东西存在呢?

        追根溯源往往可以帮助我们理解事情本质

        在 java 诞生初期

        开发者们发现

        当需要实现事件监听、线程回调时

        经常需要被迫给一个简单的任务创建一个单独的类文件

        导致项目目录变成一个“垃圾场”

        神说要有光

        于是 内部类 诞生了

        它有什么意义?

        1.更好地体现了“包含”关系,符合现实逻辑,帮助开发者更好开发

        2.不破坏封装性的前提下,访问外部类的成员属性和方法变得更方便了

        3.内部类同样可以继承类或实现接口,间接实现了多重继承的效果       

        4.代码瘦身:避免了类名比逻辑还长的情况出现

三、内部类

        接下来我们详细介绍一下四种内部类

1、成员内部类

成员内部类是最常用的内部类,它就像是外部类的一个成员变量

特点:

        1.可以直接访问外部类的所有成员属性和成员方法(包括private、静态)

        2.在外部类中,可以直接访问内部类中所有的成员属性和方法(也包括private),但是要借助内部类的对象调用

        3.成员内部类不能定义 static 成员属性或者 static 成员方法

深度探索:非静态内部类不能定义 static 成员属性和方法-CSDN博客https://blog.csdn.net/qq_73698057/article/details/149978575?sharetype=blogdetail&sharerId=149978575&sharerefer=PC&sharesource=qq_73698057&spm=1011.2480.3001.8118        4.内部类方法中、内部类中、外部类中有同名属性,访问时遵循就近原则

public class Car {private String brand = "Toyota";private int speed = 0;// 成员内部类 - 引擎public class Engine {private int horsepower = 150;public void start() {System.out.println(brand + " 引擎启动,马力: " + horsepower);speed = 10; // 可以修改外部类的成员}public void showInfo() {System.out.println("品牌: " + brand + ", 当前速度: " + speed);}}public void drive() {// 外部类访问内部类需要创建对象Engine engine = new Engine();engine.start();engine.showInfo();}
}// 使用示例
public class Test {public static void main(String[] args) {Car car = new Car();car.drive();// 创建内部类对象的另一种方式Car.Engine engine = car.new Engine();engine.showInfo();}
}

2、静态内部类

是成员内部类的一种特殊形式

使用 static关键字 修饰,更像一个独立的类

注意:

        static 内部类中可以定义 static属性和方法

        static 内部类中只能访问外部类类中的 static 属性和方法(静态访问静态)

        外部类中可以访问 static 内部类中的所有属性和方法

public class MathUtils {private static final double PI = 3.14159;private String instanceField = "实例字段"; // 静态内部类无法访问// 静态内部类public static class Calculator {private static int count = 0;public static double circleArea(double radius) {count++; // 可以有静态成员return PI * radius * radius; // 只能访问外部类的静态成员}public static int getCount() {return count;}}
}// 使用示例
public class StaticInnerTest {public static void main(String[] args) {double area = MathUtils.Calculator.circleArea(5.0);System.out.println("圆面积: " + area);System.out.println("计算次数: " + MathUtils.Calculator.getCount());}
}

3、局部内部类(不常用)                

局部内部类定义在方法中

特点:

        作用范围只能是在当前方法中

        从内部类引用的本地变量必须是最终变量或实际上的最终变量

解释一下这句话:

        “本地变量”:指的是在方法内部定义的局部变量,包括方法参数,例如:

public class Example {public void method() {int localVariable = 10;  // 这就是本地变量class LocalInnerClass {// 在这里引用本地变量}}
}

        “最终变量”:用 final 修饰的变量

        “实际上的最终变量”:jdk8 引入的概念,即使没有显示使用 final 关键字,但是如果变量在初始化之后从未被修改,那么它就被认为是实际上的最终变量

        也就是说,局部内部类里想修改变量值是不可以的,只能修改常量

public class LocalInnerExample {public void processData() {final int multiplier = 10; // 必须是final或实际上final// 局部内部类class LocalProcessor {public void process(int value) {System.out.println("处理结果: " + (value * multiplier));}}LocalProcessor processor = new LocalProcessor();processor.process(5);}
}

4、匿名内部类——某种意义上可以替代接口和抽象类

没有名字的内部类

本身是一个特殊的局部内部类(定义在方法中)

注意:

        匿名内部类必须依托于一个接口或者一个父类(这个父类可以是抽象类或者普通类)

        匿名内部类在声明的时候就要创建对象,否则后面无法创建

        匿名内部类中无法定义构造器

功能:

        1.匿名内部类实现接口

        2.匿名内部类实现抽象类

        3.匿名内部类对象使用父类构造方法

// 定义一个接口
interface ClickListener {void onClick();
}// 定义一个抽象类
abstract class Animal {abstract void makeSound();public void sleep() {System.out.println("动物在睡觉");}
}public class AnonymousInnerExample {public static void main(String[] args) {// 1. 实现接口的匿名内部类ClickListener button = new ClickListener() {@Overridepublic void onClick() {System.out.println("按钮被点击了!");}};button.onClick();// 2. 继承抽象类的匿名内部类Animal dog = new Animal() {@Overridevoid makeSound() {System.out.println("汪汪汪!");}};dog.makeSound();dog.sleep();// 3. 直接使用匿名内部类处理事件(常见用法)processClick(new ClickListener() {@Overridepublic void onClick() {System.out.println("这是匿名处理的点击事件");}});}public static void processClick(ClickListener listener) {listener.onClick();}
}

四、易踩坑的点

创建内部类对象的语法易出错:

public class CreationError {class Inner {void display() {System.out.println("内部类方法");}}public static void main(String[] args) {CreationError outer = new CreationError();// 错误的创建方式// Inner inner = new Inner(); // 编译错误// 正确的创建方式Inner inner1 = outer.new Inner(); // 方式1Inner inner2 = new CreationError().new Inner(); // 方式2}
}

http://www.lryc.cn/news/612311.html

相关文章:

  • MATLAB深度学习之数据集-数据库构建方法详解
  • 202506 电子学会青少年等级考试机器人三级实际操作真题
  • KVazaar:开源H.265/HEVC编码器技术深度解析
  • 三、Istio流量治理(二)
  • 进程管理块(PCB):操作系统进程管理的核心数据结构
  • Linux systemd 服务管理与 Firewall 防火墙配置
  • envFrom 是一个 列表类型字段bug
  • LeetCode:1408.数组中的字符串匹配
  • 面向流程和产品的安全档案论证方法
  • PostgreSQL 高可用与负载均衡
  • DDoS 防护的未来趋势:AI 如何重塑安全行业?
  • MySQL各版本差异对比小工具
  • 贪心算法学习 跳跃游戏
  • CDP集群中通过Hive外部表迁移HBase数据的操作记录
  • mysql 8递归查询
  • Java基础学习(三):输入输出、控制流程、大数值、数组
  • 客流特征识别准确率提升 29%:陌讯多模态融合算法在零售场景的实战解析
  • 数据结构与算法的认识
  • Android 之 ViewBinding 实现更安全、高效的视图绑定
  • 【渲染流水线】[应用阶段]-[裁剪]以UnityURP为例
  • CGAL Kernel 和 Traits 类深度解析:从官方教程到实践应用
  • prefetch 下载 GEO 数据注意事项
  • Milvus 向量数据库
  • 使用 Helm 在 Kubernetes 中安装 Milvus
  • 安装向量数据库Milvus
  • C++实现线程池(3)缓存线程池
  • Chrontel昆泰-【CH7036A-BF】CH7036 LVDS to HDMI/VGA/LVDS Converter
  • ​ubuntu22.04系统入门 (四)linux入门命令 权限管理、ACL权限、管道与重定向
  • Qt菜单栏与工具栏实战
  • 学习 Android(十四)NDK基础