JDK5.0新特性之:枚举

JDK5.0新特性之:枚举

文/陈刚 2005-11-09 

一、前言

  JDK5.0出来有快一年了吧,泛泛的浏览过一些资料,不知道是文章写得生涩,还是我愚笨,总之是没太明白。反正所做的项目也没有用到,所以放在了一边。近来公司平台升级到JBOSS4和JDK5,看来要仔佃看它一看看。上网搜索了一些资料,花了两小时阅读,算明白了一些,好象也不是很难。现将心得和理解结集成文,以便后来者。

  JDK5.0主要有哪些新特性呢?如下列表

  • 泛型
  • 增强的for循环
  • 自动装箱和自动拆箱
  • 类型安全的枚举
  • 可变长度参数
  • 静态引入
  • 元数据(注解)
  • C风格的格式化输出

  本文先讲“类型安全的枚举”。

二、旧的历史

  举个例:有一个如下的“花(flower)”类,它有一个颜色(color)属性,用int型来表示其颜色。

public class Flower {
    private int color;
    public void setColor(int color) {
        this.color = color;
    }
   
    public int getColor(){
        return color;
    }
}

  这时一般我们会创建一个常量类,来存放颜色常量,如下:

public interface Color {
    int RED = 0;
    int BLACK = 1;
    int YELLOW = 2;
    int BLUE = 3;
    int WHITE = 4;
    int ORANGE = 5;
}

  以后我们用的时候就可以这样:

public class Client {
    public static void main(String[] args) {
        Flower f = new Flower();
        f.setColor(Color.RED);
    }
}

  Color类就是一个我们自己来实现的枚举类,当然它并不是严格意义上的枚举类,而且JDK5.0之前还没有枚举。这时会出现一个问题:setColor参数是int型,那么也许用户会不小心用一个非法的int值赋进去,这样就可能产生BUG,如:f.setColor(100);显示100并非是我们设定中的颜色值。

  在那本有名的java著作<<Effective java>> Joshua Bloch,用了专门的一章(第5章)来讨论这个问题,书中给出了一个比较严谨的解决方案,如下代码所示

(1)用Color类更改如下:

public class Color {
    private final int color;
    private Color(int color) {
        this.color = color;
    }
    public int getColorValue() {
        return color;
    }
    public static final Color RED = new Color(0);
    public static final Color BLACK = new Color(1);
    public static final Color YELLOW = new Color(2);
    public static final Color BLUE = new Color(3);
    public static final Color WHITE = new Color(4);
    public static final Color ORANGE = new Color(5);
}

(2)Flower类也要相应的更改,将int改为Color型。

public class Flower {
    private Color color;
    public void setColor(Color color) {
        this.color = color;
    }
    public Color getColor() {
        return color;
    }
}

(3)客户端Client不用修改。

  这样Flower类的setColor方法就只接收Color,也不用担心用户不心传入非法的参数值了。

三、新的特性:JDK5.0枚举

(1)简单的例子

  JDK5.0的枚举,正好可以解决上面我们讨论的问题,而且更简洁。还是用上面的代码做示例,只需要将Color类修改如下,Flower、Client都无法更改。

public enum Color {
    RED, BLACK, YELLOW, BLUE, WHITE, ORANGE
}

 很简单吧。接下来我们做更深一步的说明:

  • 所有枚举类都是java.lang.Enum的子类(JDK内核自动将Color隐性继承自Enum)
  • RED...ORANGE都是Color的实例对象

 上面的Color枚举类,功能好象还和以前的例子不完全一样,我们再次修改如下。

public enum Color {
    RED(0), BLACK(1), YELLOW(2), BLUE(3), WHITE(4), ORANGE(5);
   
    int color;
    Color(int color){
        this.color=color;
    }
   
    public int getColorValue(){
        return color;
    }
}

  从这里我们可以看到枚举类是如何创建构造函数及方法的,有一些隐性的东西要说明一下:

  • 枚举类的构造函数要求是private的,如果象例子里那样不加修饰符,则Java会自动给加上。但如果你想加上public则会报错。
  • RED(0), BLACK(1)...等枚举值必须定义在前面,而且最后一个枚举值ORANGE(5);未尾用分号结束。

(2)在循环中使用枚举类

  枚举类都有一个values方法可以得到它值的数组:Color[] colors=Color.values();而且枚举类都支持泛型(以后的文章会重点说到),所以我们可以这样来遍历这个数组:

        Color[] colors = Color.values();
        for (Color c : colors) {
            System.out.println("color value=" + c.getColorValue());
        }

更简洁的写法是这样:

        for (Color c : Color.values()) {
            System.out.println("color value=" + c.getColorValue());
        }

(3)在switch(分支)中使用枚举

  如下代码示例,这里要注意将“case RED:”写成“case Color.RED:”是会报错的,因为JDK5.0可以自动根据“switch (color)”就判断入你要使用什么枚举类型了。从这里也可以看出JDK5.0确实为用户做了帖心的考虑,尽量让程序员少写代码,写更简单的代码。

        Color color = Color.RED;
        switch (color) {
        case RED:
            //process ...
            break;
        case BLACK:
            //process ...
            break;
        case WHITE:
            //process ...
            break;
        default:
            //process ...
        }

(4)JDK5.0新增的集合:EnumMap 和EnumSet

  给出两个例子,一切尽在不言中了。(说明:这两个例子用到了JDK5.0中泛型的知识)

        Map<Color, String> map = new EnumMap<Color, String>(Color.class);
        map.put(Color.RED, "红色");
        map.put(Color.BLACK, "黑色");
        map.put(Color.WHITE, "白色");
       
        for (Color c : Color.values()) {
            System.out.println(c + " chinese is: " + map.get(c));
        }

        Set all = EnumSet.allOf(Color.class);
        EnumSet warmColors = EnumSet.of(Color.RED, Color.YELLOW);
        Set notWarmColors = EnumSet.complementOf(warmColors);
        Set notBlack = EnumSet.range(Color.RED, Color.YELLOW);

四、参考资料

http://dev.yesky.com/451/2044451_1.shtml

五、作者简介

陈刚,广西桂林人,著作有《Eclipse从入门到精通》
您可以通过其博客了解更多信息和文章:http://www.ChenGang.com.cn

你可能感兴趣的:(JDK5.0新特性之:枚举)