你知道 Java 中关键字 enum 是一个语法糖吗?反编译枚举类
ninehua 2025-07-14 20:34 4 浏览
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
写下这篇文章,也纯属于是一个机缘巧合,我一个非常要好的朋友程,也是刚刚踏上工作岗位。
这个问题也是他踏上岗位的两三天,遇到的~ 起初我也是不会的~ 菜鸡==我
然后就写下了这篇文章~
奇怪的开始
他最初的问题,把我问的完全摸不着头脑
当时我看到就很懵~ 给了一个当时的第一印象的回答
(图片说明:两个打错别字的憨憨)
随后他手敲了代码扔给了我~
奇怪的代码
接口信息
/**
* 可自描述的枚举类型的基类
* @author 宁在春
*/
public interface DescribableEnum {
/**
* @return 获取数字型的代码
*/
int getCode();
/**
* @return 获取该枚举的描述名(PS:不是枚举字段的英文名,而是中文描述)
*/
String getName();
/**
* @return 获取该枚举的原生名(PS:不是枚举的中文描述,而是字段的英文名)
*/
String name();
static <T extends DescribableEnum> T getByCode(Class<T> enumClazz, Integer code) {
return Arrays.stream(enumClazz.getEnumConstants())
.filter(candidate -> Objects.equals(candidate.getCode(), code))
.findFirst()
.orElse(null);
}
static <T extends DescribableEnum, P> T getByProperty(Class<T> enumClazz, Function<T, P> property, P value) {
return Arrays.stream(enumClazz.getEnumConstants())
.filter(candidate -> Objects.equals(property.apply(candidate), value))
.findFirst()
.orElse(null);
}
}
复制代码
实现接口的枚举类
/**
* @author 宁在春
*/
@Getter
@RequiredArgsConstructor
public enum SeasonEnum implements DescribableEnum {
SPRING(1,"春天"),
SUMMER(2,"夏天"),
AUTUMN(3,"秋天"),
WINTER(4,"冬天");
private final int code;
private final String name;
}
复制代码
不瞒你说,我看完代码我也是仍然是十分懵逼的。
一方面它说这个代码运行起来没有报错,另外一方面,这个枚举类它确实没实现全部的接口,这和我学的Java就有所相斥。
虽然我很肯定,这个枚举类一定是实现了全部的接口方法的,但是我没敲,没在IDE中跑过代码,没底气讲,哈哈。然后我就说~
感觉自己真的菜的扣jio~
有了idea,立马我又站起来了
回到住房,我立马就把他给的代码敲了一遍~ 然后我就发现 idea 立马就给出了答案。
接口中总共有三个方法~
int getCode();
String getName();
String name();
//但真正没被实现的方法就只有 String name();
//其他的两个都已经由 lombok 的注解 @Getter 实现啦~
复制代码
但是在idea中冒出了这个小绿标,证明肯定是被实现啦的~
我就直接点了一下~
然后我发现我们所写的枚举类,在我们不知道的情况下
还给我们直接继承了底层的抽象枚举类enum,让我的Java基础再一次深受打击,感觉自己好菜吧菜~~
看完这里我很好奇,我的idea能点(2022版本),为啥他的不行 ,理应找到这个抽象类,顺着往下找就能解决问题啦。
好奇 enum 的底层
但是找到这里的时候,我自己好奇起来啦~
我好奇我们写的枚举类~ 在什么时候给我继承了那个抽象类~
我去看了编译完的class文件,并没有看到我想要的信息,这就让我更好奇啦
我接着就去互联网搜索资料~
看到很多的小伙伴说,在idea看到的class文件,是不会体现 enum 的这个继承类的,都说要反编译这个class文件才行。
反编译这事本来是很简单的,Jdk 自带反编译命令,用 javac 就行,但是我电脑的jdk,不知道是犯了啥问题,让我整了半小时,都没成功用上 javac 命令。
最后放弃了,看见就想砸啦
反编译
下载 jad
用了另外一个常用的反编译工具 jad
下载地址:jad
选择自己合适的版本,我是windows 10 选的是第一个~
下载之后解压就是这样的
配置Path 路径,方便全局使用~
配置完,直接在命令行,输入个 jad 看成功莫
展示为上图这样,则表示已经成功啦。
反编译
接下来我们就来反编译我们的代码吧
jad 类名.class
当执行这条命令,就会看到一个.jad结尾的文件生成~
拿 idea 打开或者是 nodepad++ 打开都可~
从这个文件可以看到,我们编写 SeasonEnum 类确确实实是继承了 enum类~
也让我想起了一个比较常识性的面试题:
为什么枚举类不能够继承啊?看到这个反编译出来的文件就全都明白啦,它是个final修饰的类啊~
补充:idea 集成 jad
上面那样操作还是感觉有点麻烦的,喜欢命令行的小伙伴,会觉得其实也还好,毕竟不用动鼠标,感觉会爽很多~
使用:
直接在class文件上鼠标右键:
点击完,就会在当前文件目录下生成一个 FileName.jad 的文件。 直接在idea中打开即可查看~
两个泛型方法的使用
对于接口中定义的那两个方法,可能会有小伙伴不太会用~
我这里重新贴一下,一个一个的补充说明一下
第一个方法:getByCode
static <T extends DescribableEnum> T getByCode(Class<T> enumClazz, Integer code) {
return Arrays.stream(enumClazz.getEnumConstants())
.filter(candidate -> Objects.equals(candidate.getCode(), code))
.findFirst()
.orElse(null);
}
复制代码
我先说这个方法的作用吧,就是根据你传入枚举类和code值,获取枚举类对象。
这个还是非常简单的,就是用到了 Java 8 的 Stream 流操作,还有 optional 的操作~ 都是见名知意的,不懂也明白意思。
我拆开说一下:
- enumClazz.getEnumConstants()的意思是获取传过来的枚举类的所有枚举元素,如果enumClazz不为枚举类则返回空
- Arrays.stream()这个就是以指定的数组作为来源创建一个流
- filter是Stream 流中的一个过滤数据的方法,过滤的逻辑是自己写的。
- findFirst就是取第一个值
- orElse(null) 没有值就为空。
- T就是泛型,这个我寻思大家都知道吧~
使用:
SeasonEnum seasonEnum = DescribableEnum.getByCode(SeasonEnum.class, 1);
System.out.println(seasonEnum);
/**
* out
*/
复制代码
再来看第二个:getByProperty
static <T extends DescribableEnum, P> T getByProperty(Class<T> enumClazz, Function<T, P> property, P value) {
return Arrays.stream(enumClazz.getEnumConstants())
.filter(candidate -> Objects.equals(property.apply(candidate), value))
.findFirst()
.orElse(null);
}
复制代码
这个方法的流程:
- 就是通过你传入的枚举类class对象、Function 函数和值,
- 在传入的枚举类class对象中通过getEnumConstants()方法获取到所有的枚举元素,
- 然后再通过你传入的 function 函数获取到当前枚举元素的值和你传入的值进行比较,成功则保留在此次的流数据中,过滤完后,依然是取第一个枚举类对象的。
使用方法:
public static void main(String[] args) {
SeasonEnum seasonEnum = DescribableEnum.getByCode(SeasonEnum.class, 1);
System.out.println(seasonEnum);
SeasonEnum byProperty = DescribableEnum.getByProperty(SeasonEnum.class, (s -> s.getCode()), 2);
System.out.println(byProperty);
SeasonEnum byProperty2 = DescribableEnum.getByProperty(SeasonEnum.class, (s -> s.getName()), "冬天");
System.out.println(byProperty2);
/**
* out
* SPRING
* SUMMER
* WINTER
*/
}
复制代码
function 函数不懂的小伙伴,可以去看看 Java 8 实战的这本书,讲的很好滴~ 对于lambda表达式、stream流、optional 操作等都做了很好的讲解,还有 Java 8 的LocalDatetime 的讲解.
其实还有很多关于枚举类的问题是没有讲到的,但是遇到那些问题,只要你反编译出枚举类的代码,一切都会变得显而易见的。
说起来这一切都是基础问题,都是在平常开发中被忽略掉了,今年也是我写 Java基础方面的文章最频繁的时候,没有再刻意追求那些框架的知识,反而是对反射、泛型、Lambda、Stream、Optional、注解等等非常感兴趣。
以前也不是说不会用,而是对一些东西都是处于一知半解的状态。
后记
今天就写到了这里啦~ 感觉自己还好菜啊~ 一起努力哦~
不知道你是否也知道 enum类也是一个近似语法糖的东西吗?
希望你是满载而归的~
也希望在这里,能留下属于你的赞和关注,哈哈,更加希望大家能够踊跃发言,愉快的交流~
相关推荐
- 配合制导弹药!土耳其推出反无人机武器系统,可全天候拦截无人机
-
【军武次位面】作者:FriedrichLau据报道,日前土耳其军队装备了一款名为Sahin"沙欣"的反无人机武器系统。该系统由土耳其Aselsan公司开发,旨在摧毁迷你或小型无人机,...
- 威纶通常见问题18 威纶通触摸屏密码使用的相关介绍
-
密码1:屏右下角的系统设定列(向左的箭头)进入密码提醒:上传下载的默认密码均为6个1,若不慎忘记密码,因已加密所以原厂也无法解开,请妥善保管密码。若因不可抗力因素造成的忘记密码,只能将屏恢复出厂设置然...
- 轻松学会威纶通触摸屏上传与反编译
-
说到上传,大家并不陌生,上传顾名思义:就是把实际触摸屏画面上传到电脑EasyBuilderPro软件上,上传的作用是什么呢?可以修改触摸屏上原有的画面,所以说在上传这两字在工控中是非常重要的,接下来进...
- DLL 可以被反编译吗?(dll文件可以编辑吗)
-
DLL可以被反编译,但存在一定难度DLL(动态链接库)是一种二进制文件,包含了可执行代码和数据。虽然它不像高级语言源代码那样容易被理解,但可以通过一些反编译工具进行逆向分析。不过,反编译后的结果通常...
- 复古游戏反编译工具遭任天堂下架 工具名或为诱因
-
Reddit用户mhjhacker1近日发表文章称,自己开发的一款“复古主机游戏逆向工程”工具被其他用户使用,反编译了一款任天堂四十年前的游戏,因而遭到了Itch.io的下架。而相关的另外三个工具也遭...
- protobuf之序列化数据和反序列化数据基础知识
-
什么是protobufProtocalBuffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化。ProtocolBuffers是一种语言无关、平台无关、可扩展的...
- MT管理器-简单实战-去除启动页(mt管理器去除登录界面)
-
每次打开APP都要看着启动页2秒,很烦人,既然如此我们把它去掉吧。学过Android开发的都知道,APP的每个界面都是一个Activity,然后你点击桌面上的图标之后,其实是启动了这个...
- 这两个强大的开源C#反编译逆向工具,探索C#桌面应用的小秘密
-
C#的应用也比较多,有时候,我们想要研究一下别人的优秀的项目,可能会借助一些非常规手段来学习。下面,我就分享几款开源的C#反编译工具。dnSpydnSpy是一个用C#开发,开源的调试器和.NET汇...
- 一款开源的.NET程序集反编译、编辑和调试神器
-
致力于发掘、评测和推荐各种高效实用的工具和软件,帮助您在工作和生活中事半功倍。项目介绍dnSpyEx是dnSpy项目的非官方Fork维护版本,一款开源、功能强大的.NET反编译工具和调试器,可用于在没...
- 记一次噩梦般的经历--论学会反编译的重要性
-
最近在做一个android项目,因为非开源,github上也没购有私有库,所以就没有提交github管理。昨天我感觉写到了一定程度,一个小的版本已经出来了,于是就想U盘和网盘都备份一下。结果出现了下面...
- 奇!AI(人工智能)能不能反编译二进制代码为高级语言Java或者C?
-
一直很好奇某些软件的制作过程,使用的算法。因为自己实现的,写的稀烂,虽然功能达到了,但处理速度和处理效率很低下,于是也尝试使用一些反编译软件,如IDAPro软件。想看看人家怎么实现,怎么做到效果那么...
- 你知道 Java 中关键字 enum 是一个语法糖吗?反编译枚举类
-
持续创作,加速成长!这是我参与「掘金日新计划·10月更文挑战」的第7天,点击查看活动详情写下这篇文章,也纯属于是一个机缘巧合,我一个非常要好的朋友程,也是刚刚踏上工作岗位。这个问题也是他踏上岗位...
- SpringBoot项目Jar包加密,防止反编译
-
场景最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去。要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来。方案第一种方案使用代码混淆采用proguard-m...
- 安卓移动应用代码安全加固系统设计及实现
-
安卓平台已经逐渐成为最受欢迎的移动终端操作系统,基于安卓系统的软件应用数量众多,同时安全威胁也在不断增加。介绍了Android系统的安全风险及加固的核心技术,据此提出了一种安卓应用程序的安全加固系统,...
- 代码安全之代码混淆(代码混淆器是干什么的)
-
防止核心代码泄露以及代码合并每日辛辛苦苦码的代码被轻松破解?机密核心模块被盗用?数据库地址和语句暴露?……这些都是由代码未混淆加密,从而进行泄露的我们目前DLL文件存在的风险:一、直接引用二、反编译...