当前位置: 首页 > 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.dtcms.com/a/318688.html

相关文章:

  • WebView 中控制光标
  • Diamond基础1:认识Lattice器件
  • 数据结构 二叉树(1)二叉树简单了解
  • Linux学习-数据结构(栈和队列)
  • 8.6学习总结
  • Selenium在Pyhton应用
  • Java 大视界 -- Java 大数据机器学习模型在电商用户生命周期价值评估与客户关系精细化管理中的应用(383)
  • 应急响应排查(windows版)
  • Vue计算属性详解2
  • Python Pandas.lreshape函数解析与实战教程
  • 机器学习模型调优实战指南
  • 关于应急响应的那些事
  • 第14届蓝桥杯Scratch选拔赛初级及中级(STEMA)真题2023年3月12日
  • 人工智能-python-机器学习实战:特征降维、PCA与KNN的核心价值解析
  • Linux: NFS 服务部署与autofs自动挂载的配置
  • 分隔串处理方法
  • SQL注入SQLi-LABS 靶场less51-57详细通关攻略
  • 【2026版】JVM面试题
  • K8S的POD数量限制
  • 敏捷协作平台推荐:Jira、PingCode、Tapd等15款
  • C++ - 仿 RabbitMQ 实现消息队列--网络通信协议设计
  • 力扣-42.接雨水
  • 云平台托管集群:EKS、GKE、AKS 深度解析与选型指南-第二章
  • java 桌面应用程序基本框架
  • 【算法训练营Day21】回溯算法part3
  • C语言:指针(1-2)
  • 亚马逊新品实现快速起量:如何设置有效的广告竞价策略
  • Java保姆级新手教程第三章(方法与数组)
  • 亚马逊广告进阶指南:广告转化的基本原理
  • 前端性能优化实战:电商首页从 10s 加载到 1s 的踩坑与复盘