第30条:用enum代替int常量

在编程语言中还没有引入枚举类型之前,表示枚举类型的常量模式是声明一组具名的int常量,每个类型成员一个常量:

1
2
3
4
5
6
7
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;

public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;

这种方法称作int枚举模式。在这种模式中使用String常量,而不是int常量。这样的变体被称为String枚举模式

Java 1.5增加了枚举类型,可以避免intString枚举模式的缺点。

1
2
public enum Apple {FUJI, PIPPIN, GRANNY_SMITH}
public enum ORANGE {NAVEL, TEMPLE, BLOOD}

举个枚举类型的好例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public enum Planet {
    MERCURY(3.302e+23, 2.439e6),
    VENUS  (4.869e+24, 6.052e6),
    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 kilograms
    private final double radius;         // In meters
    private final double surfaceGravity; // In m / s^2

    // Universal gravitational constant in m^3 / kg s^2
    private static final double G = 6.67300E-11;

    // Constructor
    Planet(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;  // F = ma
    }
}

下面是一个简短的程序,根据某个物体在地球上的重量,打印出该物体在所有8颗行星上的重量:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Takes earth-weight and prints table of weights on all planets (Page 160)
public class WeightTable {
   public static void main(String[] args) {
      double earthWeight = Double.parseDouble(args[0]);
      double mass = earthWeight / Planet.EARTH.surfaceGravity();
      for (Planet p : Planet.values())
         System.out.printf("Weight on %s is %f%n",
                 p, p.surfaceWeight(mass));
   }
}

每个Plant常量都关联了不同的数据,但你有时需要将本质上不同的行为与每个常量关联起来。

第31条:用实例域代替序数

第32条:用EnumSet替代位域

第33条:用EnumMap替代序数索引

第34条:用接口模拟可伸缩的枚举

第35条:注解优先于命名模式

第36条:坚持使用Override注解

第37条:用标记接口定义类型