Java 语言中 Enum 类型的使用介绍

本文介绍了如何在Java中使用枚举类型来简化控制流程,并提供了避免错误使用枚举的实例。通过枚举类型,可以更方便地管理一组预定义的常量值,减少错误并提高代码的可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


清单 3. 定制枚举类型
 // 定义 RSS(Really Simple Syndication) 种子的枚举类型
 public enum NewsRSSFeedEnum { 
    // 雅虎头条新闻 RSS 种子
    YAHOO_TOP_STORIES("http://rss.news.yahoo.com/rss/topstories"), 
    
    //CBS 头条新闻 RSS 种子
    CBS_TOP_STORIES("http://feeds.cbsnews.com/CBSNewsMain?format=xml"), 
    
    // 洛杉矶时报头条新闻 RSS 种子
    LATIMES_TOP_STORIES("http://feeds.latimes.com/latimes/news?format=xml"); 
        
    // 枚举对象的 RSS 地址的属性
    private String rss_url; 
        
    // 枚举对象构造函数
    private NewsRSSFeedEnum(String rss) { 
        this.rss_url = rss; 
    } 
        
    // 枚举对象获取 RSS 地址的方法
    public String getRssURL() { 
        return this.rss_url; 
    } 
 }

上面头条新闻的枚举类型增加了一个 RSS 地址的属性 , 记录头条新闻的访问地址。同时,需要外部传入 RSS 访问地址的值,因而需要定义一个构造函数来初始化此属性。另外,还需要向外提供方法来读取 RSS 地址。

如何避免错误使用 Enum

不过在使用 Enum 时候有几个地方需要注意:

  1. enum 类型不支持 public 和 protected 修饰符的构造方法,因此构造函数一定要是 private 或 friendly 的。也正因为如此,所以枚举对象是无法在程序中通过直接调用其构造方法来初始化的。
  2. 定义 enum 类型时候,如果是简单类型,那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号';'隔开,不能用逗号或空格。
  3. 由于 enum 类型的值实际上是通过运行期构造出对象来表示的,所以在 cluster 环境下,每个虚拟机都会构造出一个同义的枚举对象。因而在做比较操作时候就需要注意,如果直接通过使用等号 ( ‘ == ’ ) 操作符,这些看似一样的枚举值一定不相等,因为这不是同一个对象实例。

看下面的这个例子:

清单 4. 避免错误使用 Enum 示例
 // 定义一个一周七天的枚举类型
 package example.enumeration.codes; 

 public enum WeekDayEnum { 
    Mon(1), Tue(2), Wed(3), Thu(4), Fri(5), Sat(6), Sun(7); 

    private int index; 

    WeekDayEnum(int idx) { 
        this.index = idx; 
    } 

    public int getIndex() { 
        return index; 
    } 
 } 

 // 客户端程序,将一个枚举值通过网络传递给服务器端
 package example.enumeration.codes; 

 import java.io.IOException; 
 import java.io.ObjectOutputStream; 
 import java.io.OutputStream; 
 import java.net.InetSocketAddress; 
 import java.net.Socket; 
 import java.net.UnknownHostException; 

 public class EnumerationClient { 

    public static void main(String... args) throws UnknownHostException, IOException { 
        Socket socket = new Socket(); 
  // 建立到服务器端的连接
        socket.connect(new InetSocketAddress("127.0.0.1", 8999)); 
    // 从连接中得到输出流
        OutputStream os = socket.getOutputStream(); 
        ObjectOutputStream oos = new ObjectOutputStream(os); 
  // 将星期五这个枚举值传递给服务器端
        oos.writeObject(WeekDayEnum.Fri); 
        oos.close(); 
        os.close(); 
        socket.close(); 
    } 
 } 

 // 服务器端程序,将从客户端收到的枚举值应用到逻辑处理中
 package example.enumeration.codes; 

 import java.io.*; 
 import java.net.ServerSocket; 
 import java.net.Socket; 

 public class EnumerationServer { 

    public static void main(String... args) throws IOException, ClassNotFoundException { 
        ServerSocket server = new ServerSocket(8999); 
  // 建立服务器端的网络连接侦听
        Socket socket = server.accept(); 
  // 从连接中获取输入流
        InputStream is = socket.getInputStream(); 
        ObjectInputStream ois = new ObjectInputStream(is); 
  // 读出客户端传递来的枚举值
        WeekDayEnum day = (WeekDayEnum) ois.readObject(); 
  // 用值比较方式来对比枚举对象
        if (day == WeekDayEnum.Fri) { 
            System.out.println("client Friday enum value is same as server's"); 
        } else if (day.equals(WeekDayEnum.Fri)) { 
            System.out.println("client Friday enum value is equal to server's"); 
        } else { 
            System.out.println("client Friday enum value is not same as server's"); 
        } 
        
  // 用 switch 方式来比较枚举对象
        switch (day) { 
            case Mon: 
                System.out.println("Do Monday work"); 
                break; 
            case Tue: 
                System.out.println("Do Tuesday work"); 
                break; 
            case Wed: 
                System.out.println("Do Wednesday work"); 
                break; 
            case Thu: 
                System.out.println("Do Thursday work"); 
                break; 
            case Fri: 
                System.out.println("Do Friday work"); 
                break; 
            case Sat: 
                System.out.println("Do Saturday work"); 
                break; 
            case Sun: 
                System.out.println("Do Sunday work"); 
                break; 
            default: 
                System.out.println("I don't know which is day"); 
                break; 
        } 
        
        ois.close(); 
        is.close(); 
        socket.close(); 
    } 
 }

打印结果如下:

 client Friday enum value is equal as server's 
 Do Friday work

通过程序执行结果,我们能够发现在分布式条件下客户端和服务端的虚拟机上都生成了一个枚举对象,即使看起来一样的 Fri 枚举值,如果使用等号‘ == ’进行比较的话会出现不等的情况。而 switch 语句则是通过 equal 方法来比较枚举对象的值,因此当你的枚举对象较复杂时候,你就需要小心 override 与比较相关的方法,防止出现值比较方面的错误。

Enum 相关工具类

JDK5.0 中在增加 Enum 类的同时,也增加了两个工具类 EnumSet 和 EnumMap,这两个类都放在 java.util 包中。EnumSet 是一个针对枚举类型的高性能的 Set 接口实现。EnumSet 中装入的所有枚举对象都必须是同一种类型,在其内部,是通过 bit-vector 来实现,也就是通过一个 long 型数。EnumSet 支持在枚举类型的所有值的某个范围中进行迭代。回到上面日期枚举的例子上:

 enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun }

你能够在每周七天日期中进行迭代,EnumSet 类提供一个静态方法 range 让迭代很容易完成:

 for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) { 
     System.out.println(day); 
 }

打印结果如下:

 Mon 
 Tue 
 Wed 
 Thu 
 Fri

EnumSet 还提供了很多个类型安全的获取子集的 of 方法,使你很容易取得子集:

 EnumSet<WeekDayEnum> subset = EnumSet.of(WeekDayEnum.Mon, WeekDayEnum.Wed); 
      for (WeekDayEnum day : subset) { 
          System.out.println(day);  
      }

打印结果如下:

 Mon 
 Wed

与 EnumSet 类似,EnumMap 也是一个高性能的 Map 接口实现,用来管理使用枚举类型作为 keys 的映射表,内部是通过数组方式来实现。EnumMap 将丰富的和安全的 Map 接口与数组快速访问结合到一起,如果你希望要将一个枚举类型映射到一个值,你应该使用 EnumMap。看下面的例子:

清单 5. EnumMap 示例
 // 定义一个 EnumMap 对象,映射表主键是日期枚举类型,值是颜色枚举类型
 private static Map<WeekDayEnum, RainbowColor> schema = 
            new EnumMap<WeekDayEnum, RainbowColor>(WeekDayEnum.class); 
    
 static{ 
    // 将一周的每一天与彩虹的某一种色彩映射起来
    for (int i = 0; i < WeekDayEnum.values().length; i++) { 
        schema.put(WeekDayEnum.values()[i], RainbowColor.values()[i]); 
    } 
 } 
 System.out.println("What is the lucky color today?"); 
 System.out.println("It's " + schema.get(WeekDayEnum.Sat));

当你询问周六的幸运色彩时候,会得到蓝色:

清单 6. 运行结果
 What is the lucky color today? 
 It's BLUE

结束语

Enum 类型提出给 JAVA 编程带了了极大的便利,让程序的控制更加的容易,也不容易出现错误。所以在遇到需要控制程序流程时候,可以多想想是否可以利用 enum 来实现。

参考资料

学习

讨论

  • 加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值