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

Java内部类的应用分析

最近看了几篇博客,又温习了一次内部类相关的内容,感觉有必要在这方面写点博客记录一下,毕竟我个人接触的也不多,平时写代码也不常用,方便以后再次温习。

啥是内部类呢,简单来说就是写在类里面的类(Inner Class),也被叫做嵌套类(Nested Class)
 

class Outer {class Inner {// 定义了一个Inner Class}
}

具体的介绍可以看这里:内部类 - Java教程 - 廖雪峰的官方网站 (liaoxuefeng.com),我在这里就不多赘述了。

内部类是一个统称,具体的分类有哪些呢?

内部类的主要应用

  • 访问外部类的私有成员,类似于写一个getter/setter方法,提供了一个外部管理私有字段的方法。我们来举个例子:
    public class Outer {private String outerField = "Hello from Outer Class!";// 成员内部类class Inner {void displayOuterField() {// 内部类访问外部类的私有成员System.out.println(outerField);}}// 创建内部类的实例并调用其方法void createInner() {Inner inner = new Inner();inner.displayOuterField();}public static void main(String[] args) {Outer outer = new Outer();outer.createInner();  // 调用外部类的方法}
    }
    

  • 封装代码,从第一条就能看出来。
  • 简化代码结构,例如想要手动实现一个表,那么这个表的数据结构肯定会占很大篇幅,这时候不妨把代码放到内部类,和其他逻辑区分开。比如我们来写一个图的结构:
    import java.util.ArrayList;
    import java.util.List;public class Graph {// 内部类表示图的顶点class Vertex {String name;List<Vertex> adjacentVertices;// 构造函数Vertex(String name) {this.name = name;this.adjacentVertices = new ArrayList<>();}// 添加邻接顶点void addAdjacent(Vertex vertex) {adjacentVertices.add(vertex);}// 打印顶点及其邻接顶点void display() {System.out.print("Vertex: " + name + " is connected to: ");for (Vertex v : adjacentVertices) {System.out.print(v.name + " ");}System.out.println();}}private List<Vertex> vertices;// 构造函数public Graph() {this.vertices = new ArrayList<>();}// 添加顶点public Vertex addVertex(String name) {Vertex vertex = new Vertex(name);vertices.add(vertex);return vertex;}// 打印所有顶点public void displayGraph() {for (Vertex vertex : vertices) {vertex.display();}}public static void main(String[] args) {Graph graph = new Graph();Graph.Vertex v1 = graph.addVertex("A");Graph.Vertex v2 = graph.addVertex("B");Graph.Vertex v3 = graph.addVertex("C");// 添加邻接关系v1.addAdjacent(v2);v1.addAdjacent(v3);v2.addAdjacent(v3);// 打印图的信息graph.displayGraph();}
    }
    

  • 处理监听事件,这个和c#的事件委托机制很像,例如有了内部类,可以把所有鼠标点击回调的逻辑放到一个内部类里,以后需要添加或修改鼠标点击的逻辑的时候,只需要修改这个内部类就可以了
    举个例子:
    import javax.swing.JButton;
    import javax.swing.JFrame;public class ButtonExample {private String buttonLabel = "Click me!";public ButtonExample() {JFrame frame = new JFrame();JButton button = new JButton(buttonLabel);// 成员内部类作为事件监听器button.addActionListener(new ButtonClickListener());frame.add(button);frame.setSize(200, 200);frame.setVisible(true);}// 内部类class ButtonClickListener implements java.awt.event.ActionListener {public void actionPerformed(java.awt.event.ActionEvent e) {System.out.println("Button clicked! Label: " + buttonLabel);}}public static void main(String[] args) {new ButtonExample();}
    }
    

  • 实现接口,或者多重继承,我们不想让外部访问到我们的实现方式,只需要在私有的内部类里面写接口的实现即可。
    // 定义接口
    interface Animal {void makeSound();  // 声明一个抽象方法
    }// 外部类
    public class AnimalShelter {// 成员内部类 Dogprivate class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("Woof!");  // 实现狗叫声}}// 成员内部类 Catprivate class Cat implements Animal {@Overridepublic void makeSound() {System.out.println("Meow!");  // 实现猫叫声}}// 方法来创建并使用内部类public void adoptAnimals() {Animal dog = new Dog();  // 创建 Dog 对象Animal cat = new Cat();   // 创建 Cat 对象dog.makeSound();  // 调用 Dog 的方法cat.makeSound();  // 调用 Cat 的方法}public static void main(String[] args) {AnimalShelter shelter = new AnimalShelter(); // 创建 AnimalShelter 对象shelter.adoptAnimals(); // 调用 adoptAnimals 方法}
    }
    

    至于静态内部类,大多是在设计模式中应用,例如实现工厂模式中的工厂类:

    public class Outer {private static int count = 0;// 静态内部类static class Inner {private int id;Inner() {this.id = ++count;  // 为每个内部类实例分配一个唯一 ID}public int getId() {return id;}}public static void main(String[] args) {Inner inner1 = new Inner();Inner inner2 = new Inner();System.out.println("Inner 1 ID: " + inner1.getId());  // 输出:Inner 1 ID: 1System.out.println("Inner 2 ID: " + inner2.getId());  // 输出:Inner 2 ID: 2}
    }
    

    方法内部类我用的较少,但是还是举个例子,这是用局部内部类(方法内部类)进行临时算法的封装

    public class Calculator {public double calculate(int base, int exponent) {// 局部静态类用于计算幂class PowerCalculator {double calculatePower() {return Math.pow(base, exponent);}}PowerCalculator powerCalculator = new PowerCalculator();return powerCalculator.calculatePower();  // 调用局部静态类的方法}public static void main(String[] args) {Calculator calculator = new Calculator();double result = calculator.calculate(2, 3);  // 2的3次方System.out.println("Result: " + result);  // 输出:Result: 8.0}
    }
    

匿名内部类比较特殊,不需要变量名,创建时自带一个生命周期,在生命周期内自动被调用,也就是说,匿名内部类一般和其他的类或者方法是绑定在一起的,由其他的类或方法来控制其行为。它的应用大概有这些:

  • 事件处理,这里先给出一个例子
    import javax.swing.JButton;
    import javax.swing.JFrame;public class ButtonExample {public static void main(String[] args) {JFrame frame = new JFrame("Button Example");JButton button = new JButton("Click me!");// 使用匿名内部类实现 ActionListenerbutton.addActionListener(new java.awt.event.ActionListener() {@Overridepublic void actionPerformed(java.awt.event.ActionEvent e) {System.out.println("Button clicked!");}});frame.add(button);frame.setSize(200, 200);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
    }
    

    这里和C#的事件委托机制是一样的,只是java有些区别罢了,创建的事件类并没有一个确切的名字,它单纯是和我们的buttonclick绑定在了一起,每次这个按钮被点击,就会激活这个事件,但是具体这个事件较什么名字我们并不清楚,只知道要让这个事件去做一些事,调一些函数。

  • 代码简化
    public class AnimalExample {public static void main(String[] args) {// 使用匿名内部类实现接口Animal dog = new Animal() {@Overridepublic void makeSound() {System.out.println("Woof!");}};dog.makeSound();  // 输出:Woof!}
    }
    
  • 实现比较器,集合排序的时候是需要一个比较器的,也就是我们排序需要一个规则,这和数据库的理论很像,这个时候我们可以用匿名内部类来实现Comparator接口:
    import java.util.Arrays;
    import java.util.Comparator;public class SortExample {public static void main(String[] args) {String[] names = {"Alice", "Bob", "Charlie"};// 使用匿名内部类实现ComparatorArrays.sort(names, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return s1.length() - s2.length();  // 按字符串长度排序}});System.out.println(Arrays.toString(names));  // 输出:[Bob, Alice, Charlie]}
    }
    

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【千帆AppBuilder】使用Python调用基于官方的API创建图片故事的应用,一起体验下全代码模式下是怎样的效果
  • PhpStorm下调试功能配置
  • KAN学习Day1——模型框架解析及HelloKAN
  • Spring boot整合接入Redis
  • shell脚本前置基础
  • 揭秘组合模式:C++设计模式的奥秘与应用!
  • 《基础模型时代的图像分割》研究综述
  • 视频素材网站无水印的有哪些?热门视频素材网站分享!
  • 文心快码帮你解大厂面试题:一次请求从浏览器进入到Sping框架的服务,整个请求的生命周期是什么?
  • HTB-lgnition(curl工具、yakit、 弱口令)
  • Git —— 2、配置本地与远程免密仓库免密访问、实操创建本地仓库与上github新仓库关联
  • stm32之硬件I2C读写MPU6050陀螺仪、加速度传感器应用案例
  • 2024杭电6
  • Spring之整合Mybatis底层源码解析
  • 万字文档带你走进Python的世界
  • SegmentFault for Android 3.0 发布
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • CentOS从零开始部署Nodejs项目
  • IndexedDB
  • Java教程_软件开发基础
  • Linux下的乱码问题
  • 成为一名优秀的Developer的书单
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 关于for循环的简单归纳
  • 免费小说阅读小程序
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 线上 python http server profile 实践
  • No resource identifier found for attribute,RxJava之zip操作符
  • kubernetes资源对象--ingress
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​secrets --- 生成管理密码的安全随机数​
  • # 服务治理中间件详解:Spring Cloud与Dubbo
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • #define,static,const,三种常量的区别
  • #微信小程序:微信小程序常见的配置传旨
  • (26)4.7 字符函数和字符串函数
  • (3)选择元素——(17)练习(Exercises)
  • (Charles)如何抓取手机http的报文
  • (day 12)JavaScript学习笔记(数组3)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (SpringBoot)第二章:Spring创建和使用
  • (多级缓存)多级缓存
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (一)80c52学习之旅-起始篇
  • (一)Java算法:二分查找
  • (一一四)第九章编程练习
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)Sublime Text3配置Lua运行环境