《Java编程思想》读书笔记(四)
2022/9/5 1:23:19
本文主要是介绍《Java编程思想》读书笔记(四),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言:三年之前就买了《Java编程思想》这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第十七章到第十八章的内容,这一次记录的是第十九章到第二十章的内容,相关示例代码放在码云上了,码云地址:https://gitee.com/reminis_com/thinking-in-java
package enumerated; /** * @author Mr.Sun * @date 2022年09月02日 15:58 * * 枚举的基本特性 */ public class EnumClass { public static void main(String[] args) { for(Shrubbery s : Shrubbery.values()) { System.out.println(s + " ordinal: " + s.ordinal()); System.out.print(s.compareTo(Shrubbery.CRAWLING) + " "); System.out.print(s.equals(Shrubbery.CRAWLING) + " "); System.out.println(s == Shrubbery.CRAWLING); System.out.println(s.getDeclaringClass()); System.out.println(s.name()); System.out.println("----------------------"); } // 从字符串名称生成枚举值 for(String s : "HANGING CRAWLING GROUND".split(" ")) { Shrubbery shrub = Enum.valueOf(Shrubbery.class, s); System.out.println(shrub); } } } enum Shrubbery { GROUND, CRAWLING, HANGING }
运行结果如下图:
ordinal()方法返回一个int值,这是每个enum实例在声明时的次序,从0开始。可以使用==来比较enum实例,编译器会自动为你提供equals()和hashCode()方法。Enum类实现了Comparable 接口,所以它具有compareTo()方法。同时,它还实现了Serializable接口。
如果在enum实例上调用getDeclaringClass()方法,我们就能知道其所属的enum类。name()方法返回enum实例声明时的名字,这与使用toString()方法效果相同。valueOf()是在Enum中定义的static方法,它根据给定的名字返回相应的enum实例,如果不存在给定名字的实例,将会抛出异常。
values()的神秘之处
前面已经提到,编译器为你创建的enum类都继承自Enum类。然而,如果你研究一下Enum 类就会发现,它并没有values()方法。可我们明明已经用过该方法了,难道存在某种“隐藏的”方法吗?我们可以利用反射机制编写一个简单的程序,来查看其中的究竟∶
package enumerated; import utils.OSExecute; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Set; import java.util.TreeSet; /** * @author Mr.Sun * @date 2022年09月02日 16:10 * * 使用反射机制研究枚举类的values() */ enum Explore { HERE, THERE } public class Reflection { public static Set<String> analyze(Class<?> enumClass) { System.out.println("----- Analyzing " + enumClass + " -----"); System.out.println("Interfaces:"); for (Type t : enumClass.getGenericInterfaces()) { System.out.println(t); } System.out.println("Base: " + enumClass.getSuperclass()); System.out.println("Methods: "); Set<String> methods = new TreeSet<String>(); for (Method method : enumClass.getMethods()) { methods.add(method.getName()); } System.out.println(methods); return methods; } public static void main(String[] args) { Set<String> exploreMethods = analyze(Explore.class); Set<String> enumMethods = analyze(Enum.class); System.out.println("Explore.containsAll(Enum)? " + exploreMethods.containsAll(enumMethods)); System.out.print("Explore.removeAll(Enum): "); exploreMethods.removeAll(enumMethods); System.out.println(exploreMethods); // Decompile the code for the enum: OSExecute.command("javap G:/github/cnblogs/gitee/thinking-in-java/out/production/thinking-in-java/enumerated/Explore.class"); } } /* Output: ----- Analyzing class enumerated.Explore ----- Interfaces: Base: class java.lang.Enum Methods: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait] ----- Analyzing class java.lang.Enum ----- Interfaces: java.lang.Comparable<E> interface java.io.Serializable Base: class java.lang.Object Methods: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait] Explore.containsAll(Enum)? true Explore.removeAll(Enum): [values] Compiled from "Reflection.java" final class enumerated.Explore extends java.lang.Enum<enumerated.Explore> { public static final enumerated.Explore HERE; public static final enumerated.Explore THERE; public static enumerated.Explore[] values(); public static enumerated.Explore valueOf(java.lang.String); static {}; } *///:~
答案是,values()是由编译器添加的static方法。可以看出,在创建Explore的过程中,编译器还为其添加了valueOf()方法。这可能有点令人迷惑,Enum类不是已经有valueOf()方法了吗。不过Enum中的valueOf()方法需要两个参数,而这个新增的方法只需一个参数。由于这里使用的Set只存储方法的名字,而不考虑方法的签名,所以在调用Explore.removeAl(Enum)之后,就只剩下【values】了。
从最后的输出中可以看到,编译器将Explore标记为final类,所以无法继承自enum。其中还有一个static的初始化子句,稍后我们将学习如何重定义该句。
由于擦除效应(在第15章中介绍过),反编译无法得到Enum的完整信息,所以它展示的Explore的父类只是一个原始的Enum,而非事实上的Enum。
由于values()方法是由编译器插入到enum定义中的static方法,所以,如果你将enum实例向上转型为Enum,那么values()方法就不可访问了。不过,在Class中有一个getEnumConstants()方法,所以即便Enum接口中没有values()方法,我们仍然可以通过Class对象取得所有enum实例∶
enum Search { HITHER, YON } public class UpcastEnum { public static void main(String[] args) { Search[] values = Search.values(); for (Search val : values) { System.out.println(val.name()); } System.out.println("--------------"); Enum e = Search.HITHER; for (Enum en : e.getClass().getEnumConstants()) { System.out.println(en); } } }
这篇关于《Java编程思想》读书笔记(四)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能
- 2024-04-14个人开发者,Spring Boot 项目如何部署
- 2024-04-14RAG应用开发实战02-相似性检索的关键 - Embedding