第六章 枚举和注解
Java支持两种特殊用途的引用类型:一种是类,称作枚举类型
;一种是接口,称作注解类型
第三十四条:用enum代替int常量
34.1 枚举类型简介
枚举类型
是指有一组固定的常量组合成合法值的类型。
34.1.1 int枚举模式
之前,我们使用一组常量来表示枚举类型 int枚举模式
public static final int APPLE_FUJI =0;
如上不具有类型安全性,可读性极差。
这里注意每个apple常量是以APPLE_为前缀,每个orange常量是以ORANGE_为前缀。这是因为没有为int枚举模式提供命名空间。前缀可以防止发生冲突。
int枚举模式是编译时常量,它们的int值会被编译到使用它们的客户端上,如果int类型上的值发生了变化,客户端必须重新编译,客户端程序还是可以运行的,不过期行为已经不再明确。而且很难将int枚举常量打印成字符串,就算打印出来,也只是一个数字,没有什么作用。
34.1.2 String枚举模式
它提供了可打印的字符串。但是新手会直接把字符串硬编码到客户端代码中,而不是使用对应的常量字段名,一旦出现书写错误那么编译时将不会被检测到,就会报错。而且性能低,因为他会依靠String的比较操作。
34.1.3 枚举类型
Java的枚举本质上是int值。
34.1.3.1 基本思想
这些类通过公有的静态final域为每个枚举常量导出一个实例。
枚举类型没有可以访问的构造器,所以它是真正的final类。客户端不能创建枚举类型的实例,也不能对它进行扩展,因此不存在实例,而只存在声明过的枚举常量。
换句话说:枚举类型是实例受控的。它们是单例的泛型化,本质上是单元素的枚举。
34.1.3.2 枚举类型的优势
枚举类型保证了编译时的类型安全。例如试图将某种枚举类型的表达式赋给另一种枚举类型的变脸,或者试图利用==操作符比较不同枚举类型的值都会导致编译时错误。
包含同名常量的多个枚举类型可以在一个系统*存。因为每个命名都有自己的命名空间。你可以增加或者重新排列枚举类型中的常量,而无需重新编译它的客户端代码,因为到处常量的域在枚举类型和它的客户端之间提供了一个隔离层:常量并没有被编译到客户端代码中,而是在int枚举模式之中。最终,可以通过调用toString方法,将枚举转换成可打印的字符串。
除了完善int枚举模式的不足之处,枚举类型还允许添加任意方法和域,并实现任意的接口。它们提供了所有的Object方法的高级实现,实现了Comparable和Serializable接口,并针对枚举类型的可任意改变性设计了序列化方式。
34.2 枚举类型演示
/**
* @author yuxingang
* date 2020-12-25 14:58
*/
public enum Plant {
MERCURY(3.302E+23, 2.439E6),
VENUS(4.869E+24, 6.025E6),
EARTH(5.975E+24, 6.378E6),
MARS(6.419E+23, 3.393E6),
JUPITER(1.899E+27, 7.149E7),
SATURN(5.685E+26, 6.027E7),
URANUS(8.683E+25, 2.556E7),
NEPTUNE(1.024E+26, 2.477E7);
private final double mass;//In KG
private final double radius;//In meters
private final double surfaceGravity;//
private static final double G = 6.67300E-11;
//Constructor
Plant(double mass, double radius) {
this.mass = mass;
this.radius = radius;
surfaceGravity = G * mass / (radius * radius);
}
public double mass() {
return mass;
}
public double radius() {
return radius;
}
public double surfaceGravity() {
return surfaceGravity;
}
public double surfaceWeight(double mass) {
return mass * surfaceGravity;
}
}