【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; 开箱即用的各类插…

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

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

手撕多线程

用一个双线程轮流打印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;记住直观的设计可以让用户体验更…

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

福州网站建设如何设计极简风格合理&#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当中&#…

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…

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 …

贪心,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><…

大型语言模型(LLMs)是怎样“学习”的?一封给网络工程师的大模型指南

数字时代&#xff0c;人工智能&#xff08;AI&#xff09;及其相关技术正日益成为许多领域的热门话题。其中&#xff0c;生成式人工智能&#xff08;Gen AI&#xff09;和大型语言模型&#xff08;LLMs&#xff09;引起了广泛的兴趣和讨论。然而&#xff0c;尽管这些术语在科技…

哪些博客类型是最受欢迎的?

在创建博客时&#xff0c;您可能会想到的最常见的问题之一是哪些是最受欢迎的博客类型&#xff1f;有许多不同类型的博客涉及广泛的主题&#xff0c;兴趣和受众。对于一个成功的博客&#xff0c;你需要提前计划并选择适合你的利基市场。在本文中&#xff0c;我们将分享您可以立…

旋转矩阵(将坐标轴旋转)

旋转矩阵&#xff08;将坐标轴旋转&#xff09; 在二维空间中&#xff0c;旋转可以用一个单一的角 定义。作为约定&#xff0c;正角表示逆时针旋转。把笛卡尔坐标的列向量关于原点逆时针旋转的矩阵是&#xff1a; 原坐标系下 坐标系逆时针旋转β 补充 sin(-a) -sin(a) co…

Google Pixel4手机刷机+Root+逆向环境详细教程

Google Pixel4手机刷机Root逆向环境配置详细教程 刷机工具下载 Windows10、Google Pixel4手机当前安卓10系统、adb工具、要刷的谷歌原生的Android11最新刷机包、安装google usb驱动、美版临时twrp-3.6.0_11-0-flame.img和美版永久twrp-installer-3.6.0_11-0-flame.zip、Magis…

程序员有什么实用神器?

程序员的实用神器 在软件开发的海洋中&#xff0c;程序员的实用神器如同航海中的指南针&#xff0c;帮助他们导航、加速开发、优化代码质量&#xff0c;并最终抵达成功的彼岸。这些工具覆盖了从代码编写、版本控制到测试和部署的各个环节。 程序员常用的一些神器包括&#xf…

C语言(递归)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

数据结构——实现通讯录(附源码)

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 点击主页&#xff1a;optimistic_chen和专栏&#xff1a;c语言&#xff0c; 创作不易&#xff0c;大佬们点赞鼓…

layui的treeTable组件,多层级上传按钮失效的问题解决

现象描述: layui的treeTable 的上传按钮在一层能用&#xff0c;展开后其他按钮正常点击&#xff0c;上传按钮无效。 具体原因没有深究&#xff0c;大概率是展开的子菜单没有被渲染treeTable的done管理到&#xff0c;导致没有重绘上传按钮。 解决方案: 不使用layu的上传组件方法…

C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍

文章目录 前言一、常见的动态内存错误1. 对NULL指针的解引用操作2. 对动态开辟空间的越界访问3. 对非动态开辟内存使用free()4. 使用free释放一块动态开辟内存的一部分5. 对同一块动态内存多次释放6. 动态开辟内存忘记释放&#xff08;内存泄漏&#xff09; 二、几个经典笔试题…