Java密封类(Sealed Classes)增强详解
Java密封类(Sealed Classes)增强详解
Java 17引入了一个重要的新特性——密封类(Sealed Classes),这一特性旨在增强Java编程语言的能力,提供了一种机制来限制哪些类可以继承一个给定的类或者实现一个给定的接口。通过sealed和permits关键字,密封类不仅增强了类型安全性,还简化了代码结构,并在编译时进行了更精确的检查。以下是对Java密封类的深入解析。
一、密封类的定义与目的
密封类是通过sealed修饰符声明的类,它限制了哪些类可以继承它。同时,使用permits关键字来指定哪些子类是被允许的。这一特性的主要目的是防止类的无序扩展,确保类的继承体系在可控范围内,减少潜在的错误和异常逻辑。
在Java 17之前,一个类要么是可以被extends的,要么是final的,只有这两种选项。如果需要控制哪些类可以继承,通常只能通过改变类的访问级别,比如去掉类的public,将访问级别设为默认(包私有)。然而,这种方法并不能完全满足对类继承关系的细粒度控制需求。密封类的引入,正是为了解决这一问题。
二、密封类的语法与用法
密封类的语法如下:
public sealed class 父类名 permits 子类1, 子类2, ... {// 类成员
}public final class 子类1 extends 父类名 {// 子类1成员
}public sealed class 子类2 extends 父类名 permits 子类2_1, ... {// 子类2成员
}// 或者
public non-sealed class 子类3 extends 父类名 {// 子类3成员,子类3可以被任意类继承
}
在上面的语法中,父类被声明为sealed,并通过permits关键字指定了允许继承它的子类。子类可以是final的(禁止继承),也可以是sealed的(限制继承),还可以是non-sealed的(恢复开放继承)。
例如,假设我们有一个表示形状的类Shape,我们希望只有Circle、Rectangle和Square这三个类可以继承它,那么我们可以这样定义:
public sealed interface Shape permits Circle, Rectangle, Square {// Shape接口的成员
}public final class Circle implements Shape {// Circle类的成员
}public sealed class Rectangle implements Shape permits Square {// Rectangle类的成员
}public final class Square extends Rectangle {// Square类的成员
}
在这个例子中,Shape是一个密封接口,它只允许Circle、Rectangle和Square这三个类实现。同时,Rectangle也被声明为密封类,它只允许Square作为其子类。这样的设计使得类的继承体系更加清晰和可控。
三、密封类的优势与特点
- 增强类型安全性
密封类通过限制类的继承关系,可以减少类型转换的错误和潜在的运行时异常,提高程序的稳定性。例如,在上面的Shape例子中,由于我们限制了哪些类可以实现Shape接口,因此在编译时就可以检查到任何非法的继承关系,从而避免运行时错误。
- 简化代码结构
密封类可以减少需要显式声明的类和接口数量,简化代码结构。例如,在上面的例子中,我们不需要为Shape接口编写额外的防御性代码来防止未知的子类实现它,因为密封机制已经保证了只有指定的子类可以实现它。
- 提高代码的可读性和可维护性
在框架和库的设计中,使用密封类可以更好地控制类的继承体系,减少代码耦合性,提高代码的可读性和可维护性。例如,在图形库中,类的作者可能希望只有特定的类可以扩展Shape,因为库的大部分工作涉及以合适的方式处理每种形状。通过使用密封类,作者可以明确地指定哪些类可以扩展Shape,从而简化库的设计和维护。
- 支持模式匹配的未来发展方向
密封类还为模式的详尽分析提供了基础,支持模式匹配的未来发展方向。在Java 14中引入的模式匹配(Pattern Matching for instanceof)特性中,密封类可以作为其基础之一,使得编译器能够在编译时检查到更多的类型信息,从而提供更精确的错误检查和代码优化。
四、密封类的限制与注意事项
- 不支持匿名类和函数式接口的继承
由于密封类需要明确的继承关系,因此不支持匿名类和函数式接口的继承。这意味着,如果一个类被声明为密封类,那么它不能被用作匿名类的父类,也不能被函数式接口所实现。
- 子类必须位于同一模块或同一包中
在密封类的声明中,permits指定的子类必须位于同一模块中(如果超类在命名模块中)或在同一包中(如果超类在未命名模块中)。这一限制确保了密封类的继承关系在编译时是可控的,避免了跨模块或跨包的非法继承。
- 子类可以是final、sealed或non-sealed
在密封类的继承体系中,子类可以是final的(禁止继承),也可以是sealed的(限制继承),还可以是non-sealed的(恢复开放继承)。然而,需要注意的是,如果一个子类被声明为non-sealed,那么它就可以被任意类继承,这可能会破坏密封类所带来的类型安全性和代码简化性。因此,在使用non-sealed子类时需要谨慎考虑。
- 编译时检查
密封类提供了编译时的类型检查,确保不会出现意外的继承关系。然而,这也意味着在编写密封类时需要注意编译器的错误提示,并根据提示进行相应的修改。
五、密封类的应用场景与示例
密封类在Java中有着广泛的应用场景,特别是在框架和库的设计中。以下是一些常见的应用场景和示例:
- 状态机模式
在状态机模式中,系统状态的变化是有限的且有明确的定义。使用密封类可以确保只有预定义的状态类可以被创建,避免了意外的状态添加。例如,一个有限状态机(FSM)可以使用密封类来定义其状态集合,并通过permits关键字来指定哪些状态是合法的转换目标。
- 图形库
在图形库中,类的作者可能希望只有特定的类可以扩展某些基类或接口。例如,在上面的Shape例子中,作者可能希望只有Circle、Rectangle和Square这三个类可以扩展Shape接口。通过使用密封类,作者可以明确地指定哪些类可以扩展Shape接口,从而简化库的设计和维护。
- API设计
在API设计中,有时需要限制某些类的继承关系以避免潜在的错误和异常逻辑。例如,一个用于处理网络通信的API可能希望只有特定的类可以扩展其基类或实现其接口。通过使用密封类,API设计者可以明确地指定哪些类可以扩展或实现这些基类或接口,从而确保API的稳定性和安全性。
六、总结与展望
Java 17中的密封类是一个重要的语言特性,它提供了对类继承关系的更细粒度控制。通过限制哪些类可以继承一个给定的类或者实现一个给定的接口,密封类增强了类型安全性、简化了代码结构,并在编译时进行了更精确的检查。这对于框架和库的设计者来说尤其有用,因为它可以更好地控制类的继承体系、减少代码耦合性、提高代码的可读性和可维护性。
未来,随着Java语言的不断发展和完善,密封类可能会得到更多的应用和优化。例如,可能会引入更多的语法和特性来支持密封类的使用;可能会与其他语言特性(如模式匹配)进行更深入的集成;可能会提供更多的工具和库来帮助开发者更好地理解和使用密封类。总之,密封类作为Java 17的一个重要特性,将为Java语言的发展和应用带来更多的可能性和机遇。
相关文章:
Java密封类(Sealed Classes)增强详解
Java密封类(Sealed Classes)增强详解 Java 17引入了一个重要的新特性——密封类(Sealed Classes),这一特性旨在增强Java编程语言的能力,提供了一种机制来限制哪些类可以继承一个给定的类或者实现一个给定的…...
鸿蒙如何自动生成二维码?QRCode组件
QRCode 用于显示单个二维码的组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 二维码组件的像素点数量与内容有关,当组件尺寸过小时,可能出现无法展示内容的情况&…...
【分布式知识】MapReduce详细介绍
文章目录 MapReduce概述1. MapReduce编程模型Map阶段Reduce阶段 2. Shuffle和Sort阶段3. MapReduce作业的执行流程4. MapReduce的优化和特性5. MapReduce的配置和调优 MapReduce局限性相关文献 MapReduce概述 MapReduce是一个分布式计算框架,它允许用户编写可以在大…...
JAVA八股
快速失败(fail-fast) 设计的目的是为了避免在遍历时对集合进行并发修改,从而引发潜在的不可预料的错误。 通过迭代器遍历集合时修改集合: 如果你使用Iterator遍历集合,然后直接使用集合的修改方法(如add(…...
关于武汉芯景科技有限公司的限流开关芯片XJ6288开发指南(兼容SY6288)
一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 1.EN引脚控制IN和OUT引脚的通断 2.OCB引脚指示状态 3.过流自动断开...
指令:计算机的语言(五)
2.9 人机交互 ASCII与二进制 对应表略 字节转移指令 lbu:加载无符号字节,从内存中加载1个字节,放在寄存器最右边8位。 sb:存储字节指令,从寄存器的最右边取1个字节并将其写入内存。 复制1个字节顺序如下…...
C#笔记(1)
解决方案: 【1】组织项目:把项目放在放在一个解决方案中,统一开发,统一编译。 【2】管理项目:开发中的任何问题,在统一编译过程中,都能随时发现。也可以添加第三方的库文件。 命名空间: 命名空…...
SSDF攻击、防御与展望
摘要: 随着无线通信业务的不断发展,频域也越来越成为了一种珍贵的稀缺资源,与此同时,相应的无线电安全问题层出不穷,为无线通信造成了十分恶劣的影响,本文从深入理解认知无线电安全开始,对一些典…...
MedMamba代码解释及用于糖尿病视网膜病变分类
MedMamba原理和用于糖尿病视网膜病变检测尝试 1.MedMamba原理 MedMamba发表于2024.9.28,是构建在Vision Mamba基础之上,融合了卷积神经网的架构,结构如下图: 原理简述就是图片输入后按通道输入后切分为两部分,一部分走…...
单点登录的要点
单点登录(SSO)是一种身份验证服务,它允许用户使用一组凭据登录一次,然后在多个应用程序中访问其他应用程序而无需重新进行身份验证。这样,用户只需一次登录即可访问整个应用生态系统,提高了用户体验并简化了…...
linux线程 | 一点通你的互斥锁 | 同步与互斥
前言:本篇文章主要讲述linux线程的互斥的知识。 讲解流程为先讲解锁的工作原理, 再自己封装一下锁并且使用一下。 做完这些就要输出一堆理论性的东西, 但博主会总结两条结论!!最后就是讲一下死锁。 那么, 废…...
全栈开发小项目
用到的技术栈: nodejswebpackknockoutmongodbPM2rabbitmq 以下是一个综合指南,展示如何将 Node.js、Webpack、Knockout.js、MongoDB、PM2 和 RabbitMQ 集成到一个项目中。 我们将在这一项目中添加 RabbitMQ,用于处理消息队列。这对于任务分…...
批处理一键创建扫描仪桌面打开快捷方式图标 简单直接有效 扫描文档图片的应急策略
办公生活中,我们在安装完多功能一体机的打印驱动之后,找不到扫描文件的地方,如果驱动程序安装正确,我们可以用系统自带的扫描仪程序调用这种打印机或复印机的扫描程序即可,它在电脑系统中的位置一般是:C:\W…...
【服务器知识】Tomcat简单入门
文章目录 概述Apache Tomcat 介绍主要特性版本历史使用场景 核心架构Valve机制详细说明请求处理过程 Tomcat安装Windows系统下Tomcat的安装与配置:步骤1:安装JDK步骤2:下载Tomcat步骤3:解压Tomcat步骤4:配置环境变量&a…...
【前端】Matter:过滤与高级碰撞检测
在物理引擎中,控制物体的碰撞行为是物理模拟的核心之一。Matter.js 提供了强大的碰撞检测机制和碰撞过滤功能,让开发者可以控制哪些物体能够相互碰撞,如何处理复杂的碰撞情况。本文将详细介绍 碰撞过滤 (Collision Filtering) 与 高级碰撞检测…...
wps图标没有坐标轴标题怎么办?wps表格不能用enter下怎么办?
目录 wps图标没有坐标轴标题怎么办 一、在WPS PPT中添加坐标轴标题 二、在WPS Excel中添加坐标轴标题 wps表格不能用enter下怎么办 一、检查并修改设置 二、检查单元格保护状态 三、使用快捷键实现换行 wps图标没有坐标轴标题怎么办 一、在WPS PPT中添加坐标轴标题 插入…...
在ESP-IDF环境中如何进行多文件中的数据流转-FreeRTOS实时操作系统_流缓存区“xMessageBuffer”
一、建立三个源文件和对应的头文件 建立文件名,如图所示 图 1-1 二、包含相应的头文件 main.h 图 2-1 mess_send.h mess_rece.h和这个中类似,不明白的大家看我最后面的源码分享 图2-2 三、声明消息缓存区的句柄 大家注意,在main.c中定义的是全局变…...
ConcurrentLinkedQueue适合什么样的使用场景?
ConcurrentLinkedQueue 是 Java 中一种无界线程安全的队列,适合多线程环境中的高并发场景。以下是一些它特别适合的使用场景: 1. 高频读操作,低频写操作 ConcurrentLinkedQueue 对于实际应用中读操作相对频繁,写操作较少的场景非…...
C语言 | Leetcode C语言题解之第480题滑动窗口中位数
题目: 题解: struct Heap {int* heap;int heapSize;int realSize;bool (*cmp)(int, int); };void init(struct Heap* obj, int n, bool (*cmp)(int, int)) {obj->heap malloc(sizeof(int) * (n 1));obj->heapSize 0;obj->cmp cmp; }bool c…...
LabVIEW开发如何实现降维打击
在LabVIEW开发中实现“降维打击”可以理解为利用软件优势和高效工具来解决复杂的问题,将多维度、多层次的技术简化为容易操作和管理的单一维度,达到出其不意的效果。以下是几种关键策略: 1. 模块化设计与封装 将复杂系统分解为若干模块&…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
