【Java】山外有山,类外还有类

【Java】山外有山,类外还有类

内部类是Java语言中的一种特性,它允许在另一个类中定义一个类。

内部类可以是静态的(不依赖于外部类的实例),也可以是非静态的(依赖于外部类的实例)。

在本篇博客中,我们将首先介绍内部类的使用特点,而后介绍几种内部类:

静态成员内部类

非静态成员内部类

局部内部类

匿名内部类

首先来看看内部类的使用特点:

image-20240505175218453

内部类的使用特点

  1. 访问控制:内部类可以直接访问外部类的成员,包括私有成员。
  2. 封装性:内部类可以隐藏在外部类中,对外不可见,增加了封装性。
  3. 继承:内部类可以继承外部类的属性和方法,也可以继承其他类或实现接口。
  4. 多态:内部类可以实现外部类不能实现的接口,实现多态。
  5. 生命周期:内部类的生命周期与创建它的外部类对象的生命周期相关联。
  6. 作用域:内部类的作用域限定在外部类中,只能在外部类中被访问。

什么时候使用内部类

当一个事物内部,还有一个部分需要完整的结构去描述,而这个内部的完整结构又仅为外部事物提供服务,则整个内部的完整结构,最好使用内部类。

例如:人类都有心脏,人类本身需要用属性去描述,人类内部的心脏,也需要特殊的属性和行为去描述,则心脏可以被定义成内部类,人类中的一个心脏类。

在实际的开发场景中,可能会有以下情形:

  1. 实现回调:使用匿名内部类来实现一个回调接口。
  2. 创建辅助类:创建一些仅供外部类使用的辅助类。
  3. 实现多态:通过内部类实现多态,特别是在设计模式中,如适配器模式、观察者模式等。

格式例如:

public class Outer {class Inner {// ...}
}

静态成员内部类

格式:直接在定义内部类的时候加上static关键字

public class A{static class B{}
}

注意:

  1. 内部类可以定义属性,方法,构造等
  2. 静态内部类可以被final或者abstract修饰,被final修饰之后,不能被继承,被abstract修饰之后,不能new
  3. 静态内部类,不能调用外部类的非静态成员
  4. 内部类还可以被四种权限修饰符修饰

调用静态内部类成员:

外部类.内部类 对象名 = new 外部类.内部类()

使用示例:

public class OuterClass {public static int staticField = 10;static class StaticInnerClass {void display() {System.out.println(staticField);}}public static void main(String[] args) {StaticInnerClass inner = new StaticInnerClass();inner.display();//或者OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();inner.display();}
}

非静态成员内部类

格式:

public class A{class B{}
}

调用非静态内部类成员:

外部类.内部类 对象名 = new 外部类().new 内部类()

使用示例:

public class OuterClass {private String outerField = "外部类字段";class NonStaticInnerClass {void display() {System.out.println(outerField);}}public void createInner() {NonStaticInnerClass inner = new NonStaticInnerClass();inner.display();}
}OuterClass outer = new OuterClass();
outer.createInner();
//或者
OuterClass.NonStaticInnerClass inner = new OuterClass().new NonStaticInnerClass();

局部内部类

局部内部类可以定义在方法中,代码块中,构造中。

例如:

  1. 辅助计算类
public class Calculator {public void calculate() {class Helper {int add(int a, int b) {return a + b;}}Helper helper = new Helper();int result = helper.add(5, 10);System.out.println("计算结果是: " + result);}
}
  1. 假如要完成临时任务
public class TaskRunner {public void runTask() {class Task {void execute() {System.out.println("执行临时任务");}}Task task = new Task();task.execute();}
}

内部类、接口、抽象类、普通类作方法参数

接口作为方法参数返回值,传递实参时,传递实现类对象。

接口作为返回值类型返回,实际返回的是实现类对象。

示例代码如下:

package com.hamburger.innerclass;public class main {public static void main(String[] args) {Mouse mouse = new Mouse();method(mouse);USB usb = method01();}/*接口作为方法参数,传递实参时,传递实现类对象*/public static void method(USB usb){usb.open();}public static USB method01(){Mouse mouse = new Mouse();return mouse;}
}
package com.hamburger.innerclass;public interface USB {public abstract void open();
}
package com.hamburger.innerclass;public class Mouse implements USB{public void open(){System.out.println("haha");}
}

抽象类

  1. 作为方法参数传递,传递实参时,传递的是其子类对象。
  2. 作为方法返回值类型返回,实际返回的是其子类对象。

普通类

  1. 作为方法参数传递,传递的是对象
  2. 作为方法返回值返回,返回的是对象

匿名内部类

匿名内部类,可以理解为没有显式声明出类名的内部类。它没有类名,通常用于创建一次性使用的类对象,特别是当需要快速实现某个接口或继承某个类时。

使用场景:我们如果想要实现接口,简单使用一次抽象方法,就需要:

创建一个实现类

实现这个接口

重写抽象方法

new实现类方法

如果我们只想单纯使用一次接口中的方法,能不能不要这么麻烦?

使用匿名内部类的方法:

  1. 创建实现类,实现接口
  2. 重写方法
  3. 创建实现类对象
  4. 调用方法

匿名内部类格式:

new 接口/抽象类(){重写方法
}.重写的方法();
===============================
类名 对象名 = new 接口/抽象类(){重写方法
}
对象名.重写的方法();

匿名内部类作为参数传递

package com.ham.niminginnerclass;
public class test {public static void main(String[] args){method(new USB() {@Overridepublic void open() {System.out.println("lzy");}@Overridepublic void close() {System.out.println("dyp");}}); }public static void method(USB usb){usb.open();usb.close();}
}package com.ham.niminginnerclass;public interface USB {public abstract void open();public abstract void close();
}

匿名内部类的使用场景:

  1. 事件监听器:在需要为事件添加监听器时,可以利用匿名内部类快速实现接口中的方法。
  2. 线程的实现:创建线程时,可以匿名内部类实现Runnable接口。
  3. 临时任务:当需要临时实现某个接口,且该实现不需要复用时。
  4. 回调函数:在需要提供回调函数时,可以使用匿名内部类快速实现。
  5. 实现策略模式:在实现策略模式时,可以使用匿名内部类来定义不同的策略。

使用示例

  1. 当需要创建一个线程来执行特定的任务时,可以使用匿名内部类实现Runnable接口:
// 使用匿名内部类创建线程
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("线程运行中");}
}).start();
  1. 在对对象数组进行排序时,可能需要提供一个自定义的比较器,这时可以使用匿名内部类:
// 使用匿名内部类实现比较器
String[] strings = {"banana", "apple", "orange"};
Arrays.sort(strings, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}
});
  1. 当需要临时实现一个接口,并且这个实现不需要在其他地方复用时,可以使用匿名内部类:
// 使用匿名内部类实现临时任务
public void performTask() {Task task = new Task() {@Overridepublic void execute() {System.out.println("执行临时任务");}};task.execute();
}

结语

参考文档如下:

【Java】内部类的使用方法和使用特点-CSDN博客

Java内部类详解(含:成员内部类、局部内部类、匿名内部类、静态内部类)-CSDN博客

36.内部类介绍_哔哩哔哩_bilibili

本篇作为复习内部类时的一部分笔记与总结,在之后仍会对本文不够详细之处作修订与补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/8445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不止是搭建 | 极空间虚拟机安装一个可做生产力的Ubuntu桌面系统以及后续优化

不止是搭建 | 极空间虚拟机安装一个可做生产力的Ubuntu桌面系统以及后续优化 哈喽小伙伴们好&#xff0c;偶是Stark-C~ 我在上篇极空间文章中不是给小伙伴们分享了使用虚拟机安装软路由固件『iStoreOS』的教程嘛&#xff1a; 打造Docker完全体&#xff0c; 开箱即用的各类插…

vue3封装获取当前年、月、季度、周

1.新建在utils文件夹中handleTime.js文件用于封装方法 // 计算当前周的开始和结束时间 export function calcNowWeek() {let startWeek moment().weekday(0).format(YYYY-MM-DD);startWeek moment(startWeek).subtract(2, days).format(YYYY-MM-DD)let endWeek moment().we…

Kafka 环境搭建之伪分布式集群模式详细教程

Kafka 简介及相关组件介绍 Kafka 环境搭建和使用之单机模式详细教程 伪集群模式 Kafka伪集群是一种在单个机器上模拟多节点Kafka集群的配置方式,主要用于开发和测试环境。在伪集群模式下,你可以配置多个Kafka broker实例,它们都连接到同一个Zookeeper实例或者集群,从而模…

通过 Java 操作 redis -- hash 哈希表基本命令

目录 使用命令 hset&#xff0c;hget 使用命令 hexists 使用命令 hdel 使用命令 hkeys&#xff0c;hvals 使用命令 hmget&#xff0c;hmset 关于 redis hash 哈希表类型的相关命令推荐看Redis - hash 哈希表 要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务…

员工满意度调查真实度难题如何攻克?

在企业管理实践中&#xff0c;员工满意度调查无疑扮演着举足轻重的角色。它不仅能够帮助企业洞察员工的真实心声&#xff0c;还是企业制定精准管理策略的重要依据。然而&#xff0c;很多时候&#xff0c;员工满意度调查的真实度却令人堪忧&#xff0c;让企业难以获得真实、有效…

手撕多线程

用一个双线程轮流打印1-100 // 定义一个类&#xff0c;用于交替打印奇偶数 public class AlternatePrinting {// 当前待打印的数字&#xff0c;初始为1private int currentNumber 1;// 用作线程间同步的锁对象private final Object lock new Object();// 程序入口public sta…

企业做网站,如何设计才有创意?

企业做网站&#xff0c;如何设计才有创意&#xff1f;我们都希望能打造一个有创意的网站建设&#xff0c;能在众多网站中脱颖而出&#xff0c;能够营销推广公司的产品&#xff0c;为公司带来更多的经济效益收益。广州网站建设的时候&#xff0c;记住直观的设计可以让用户体验更…

批处理脚本示例,用于删除特定目录下所有以 .pdb、.ilk、.lib、.map、.exp 结尾的文件:

以下是一个批处理脚本示例&#xff0c;用于删除特定目录下所有以 .pdb、.ilk、.lib、.map、.exp 结尾的文件&#xff1a; echo off set target_dirC:\path\to\directorydel /S /Q "%target_dir%\*.pdb" del /S /Q "%target_dir%\*.ilk" del /S /Q "%…

福州网站建设如何设计极简风格合理?

福州网站建设如何设计极简风格合理&#xff1f;企业网站逐渐流行&#xff0c;每个人的审美也发生着巨大的改变&#xff0c;开始追求一种极简的风格。简单的 风格才能够凸显原有的主题&#xff0c;不会太过主次不分。 越来越多的网站建设中选择极简的风格&#xff0c;简单的页面…

在Leaflet中点对象使用SVG和Canvas两种模式的对比

目录 前言 一、关于SVG和Canvas 1、SVG知识 2、Canvas知识 3、优缺点 二、SVG和Canvas在Leaflet的使用 1、相关类图 2、Leaflet的默认展示方式 三、SVG和Canvas实例及性能对比 1、SVG模式及性能对比 2、Canvas优化 总结 前言 众所周知&#xff0c;在Leaflet当中&#…

伪装坑人程序

如果直接把坑人程序复制粘贴&#xff0c;肯定会被发现&#xff0c;所以要这样&#xff01; 首先把坑人程序放到C盘的某个重要目录里这样没人注意 然后在显眼的地方创建快捷方式 然后找一个可以伪装的软件&#xff0c;就找到这个软件的快捷方式 右键单击&#xff0c;选择属性…

Datasophon基于dinky1.0.1升级到dinky1.0.2

1.首先下载dinky1.0.2版本 dinky1.0.2下载地址 2.关闭dinky1.0.1 3.升级dinky1.0.2 3.1 解压dinky1.0.2.ta.gz tar -xzvf dinky-release-1.16-1.0.2.tar.gz -C /opt/datasophon/rm -rf dinky-release-1.16-1.0.2.tar.gz复制dinky1.0.1的配置文件到dinky1.0.2目录 cp /op…

C语言易错题(隐式数据类型转换)

uint32_t num (~((uint8_t)0xFF) & 0x12345678); 误以为num计算结果为0x00000000&#xff1b; 实则num值为0x12345600&#xff1b; 原因为(uint8_t)0xFF在进行按位取反前已强制转换为32位的数据&#xff0c;故取反后的值为0xFFFFFF00&#xff0c;按位与0x12345678得到…

Flutter笔记:Widgets Easier组件库(11)- 使用提示吐丝(Tip Toasts)

Flutter笔记 Widgets Easier组件库&#xff08;11&#xff09;使用提示吐丝 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

React 学习-1

安装--使用npm 元素渲染 React只定义一个根节点&#xff0c;由 React DOM 来管理。通过ReactDOM.render()方法将元素渲染到根DOM节点上。 React 元素都是不可变的。当元素被创建之后&#xff0c;你是无法改变其内容或属性的。目前更新界面的唯一办法是创建一个新的元素&#xf…

数据结构-线性表-链表-2.3-5

试编写算法将带头结点的单链表就地逆置&#xff0c;所谓的“就地”是指辅助空间复杂度为O(1) 头插法&#xff0c;将头结点拿下&#xff0c;从第一结点开始&#xff0c;依次插入到头结点的后面直到最后一个结点为止 Linklist Reverse(Linklist L){LNode *p,*r;pL->next;L-&…

贪心,CF721 D. Maxim and Array

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 721D - Codeforces 二、解题报告 1、思路分析 如果我们当前乘积…

微信云小程序快速上手云数据库+云函数+云存储的操作

&#x1f680; 作者 &#xff1a;“二当家-小D” &#x1f680; 博主简介&#xff1a;⭐前荔枝FM架构师、阿里资深工程师||曾任职于阿里巴巴担任多个项目负责人&#xff0c;8年开发架构经验&#xff0c;精通java,擅长分布式高并发架构,自动化压力测试&#xff0c;微服务容器化k…

Options API:选项式 API改成Composition API:组合式 API的留言板

让我欢喜让我忧 改成Composition API:组合式 API的代码&#xff0c; <template><!-- start --><span class"span_checkbox">操作<input type"checkbox" v-model"showInput" value"操作" /></span><…

数据结构与算法学习笔记三---栈和队列的表示和实现(C语言)

目录 前言 一、栈 1.栈的概念 2.栈的表示和实现 1.定义 2.初始化 3.销毁 4.清空 5.栈空 6.栈的长度 7.获取栈顶元素 8.入栈 9.出栈 10.遍历 11.完整代码 二、队列 1.队列的概念 2.队列的链式表示和实现 1.定义 2.初始化 3.销毁 4.清空 5.空队列 6.队列长…