java夯实基础系列:枚举

定义

Java 代码的两个基本的构造块是 类和 接口。现在又引入了 枚举,一般简称它为enum。这个新类型允许您表示特定的数据点,这些数据点只接受分配时预先定义的值集合。

当然,熟练的程序员可以用静态常量实现这项功能,如清单 1 所示:

public class OldGrade {
  public static final int A = 1;
  public static final int B = 2;
  public static final int C = 3;
  public static final int D = 4;
  public static final int F = 5;
  public static final int INCOMPLETE = 6;
}

然后您就可以让类接受像 OldGrade.B 这样的常量,但是在这样做的时候,请记住这类常量是 Java 中 int 类型的常量,这意味着该方法可以接受任何 int 类型的值,即使它和 OldGrade 中定义的所有级别都不对应。因此,您需要检测上界和下界,在出现无效值的时候,可能还要包含一个 IllegalArgumentException 。而且,如果后来又添加另外一个级别(例如 OldGrade.WITHDREW_PASSING ),那么必须改变所有代码中的上界,才能接受这个新值。

换句话说,在使用这类带有整型常量的类时,该解决方案也许可行,但并不是非常有效。幸运的是,枚举提供了更好的方法。

定义枚举

public enum Grade {
  A, B, C, D, F, INCOMPLETE
};

在这里,我使用了新的关键字 enum ,为 enum 提供了一个名称,并指定了允许的值。然后, Grade 就变成了一个 枚举类型,您可以按清单 3 所示的方法使用它:

package com.oreilly.tiger.ch03;
public class Student {
  private String firstName;
  private String lastName;
  private Grade grade;
  public Student(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getLastName() {
    return lastName;
  }
  public String getFullName() {
    return new StringBuffer(firstName)
           .append(" ")
           .append(lastName)
           .toString();
  }
  public void assignGrade(Grade grade) {
    this.grade = grade;
  }
  public Grade getGrade() {
    return grade;
  }
}

用以前定义过的类型建立一个新的枚举( grade )之后,您就可以像使用其他成员变量一样使用它了。当然,枚举只能分配枚举值中的一个(例如, A 、 C 或 INCOMPLETE )。而且,在 assignGrade() 中是没有进行错误检测的代码,也没有考虑边界情况,请注意这是如何做到。

Java 枚举7常见种用法

enum关键字的作用类似于class或interface,本质上是在定义一个类别,细节的实现由编译器完成。
自定义的枚举类型实质上继承自java.lang.Enum抽象类。而每一个成员常量其实就是自己定义的枚举类型的一个实例,都被定义为final,所有无法改变他们,另外他们是static,pulibc的,即:
public static final 枚举常量;
在运行期间我们无法再使用该枚举类型创建新的实例,这些实例是在编译期间就完全确定下来了的。

枚举类型中的两个静态方法:
values()
获取枚举类型的所有枚举常量

valueOf(Class enumType, String name)
返回带指定名称的指定枚举类型的枚举常量。

用法一:常量

在JDK1.5 之前,我们定义常量都是: publicstaticfianl…. 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
 

1.  public enum Color {  
2.    RED, GREEN, BLANK, YELLOW  
3.  }  

用法二:switch

JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
 

Java代码 
1.  enum Signal {  
2.      GREEN, YELLOW, RED  
3.  }  
4.  public class TrafficLight {  
5.      Signal color = Signal.RED;  
6.      public void change() {  
7.          switch (color) {  
8.          case RED:  
9.              color = Signal.GREEN;  
10.             break;  
11.         case YELLOW:  
12.             color = Signal.RED;  
13.             break;  
14.         case GREEN:  
15.             color = Signal.YELLOW;  
16.             break;  
17.         }  
18.     }  
19. }  

用法三:向枚举中添加新方法

如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。
 

Java代码 
1.  public enum Color {  
2.      RED("红色"1), GREEN("绿色"2), BLANK("白色"3), YELLO("黄色"4);  
3.      // 成员变量  
4.      private String name;  
5.      private int index;  
6.      // 构造方法  
7.      private Color(String name, int index) {  
8.          this.name = name;  
9.          this.index = index;  
10.     }  
11.     // 普通方法  
12.     public static String getName(int index) {  
13.         for (Color c : Color.values()) {  
14.             if (c.getIndex() == index) {  
15.                 return c.name;  
16.             }  
17.         }  
18.         return null;  
19.     }  
20.     // get set 方法  
21.     public String getName() {  
22.         return name;  
23.     }  
24.     public void setName(String name) {  
25.         this.name = name;  
26.     }  
27.     public int getIndex() {  
28.         return index;  
29.     }  
30.     public void setIndex(int index) {  
31.         this.index = index;  
32.     }  
33. }  

用法四:覆盖枚举的方法

下面给出一个toString()方法覆盖的例子。
 

Java代码 
1.  public enum Color {  
2.      RED("红色"1), GREEN("绿色"2), BLANK("白色"3), YELLO("黄色"4);  
3.      // 成员变量  
4.      private String name;  
5.      private int index;  
6.      // 构造方法  
7.      private Color(String name, int index) {  
8.          this.name = name;  
9.          this.index = index;  
10.     }  
11.     //覆盖方法  
12.     @Override  
13.     public String toString() {  
14.         return this.index+"_"+this.name;  
15.     }  
16. }  

用法五:实现接口

所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
 

Java代码 
1.  public interface Behaviour {  
2.      void print();  
3.      String getInfo();  
4.  }  
5.  public enum Color implements Behaviour{  
6.      RED("红色"1), GREEN("绿色"2), BLANK("白色"3), YELLO("黄色"4);  
7.      // 成员变量  
8.      private String name;  
9.      private int index;  
10.     // 构造方法  
11.     private Color(String name, int index) {  
12.         this.name = name;  
13.         this.index = index;  
14.     }  
15. //接口方法  
16.     @Override  
17.     public String getInfo() {  
18.         return this.name;  
19.     }  
20.     //接口方法  
21.     @Override  
22.     public void print() {  
23.         System.out.println(this.index+":"+this.name);  
24.     }  
25. }  

用法六:使用接口组织枚举

Java代码 
1.  public interface Food {  
2.      enum Coffee implements Food{  
3.          BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
4.      }  
5.      enum Dessert implements Food{  
6.          FRUIT, CAKE, GELATO  
7.      }  
8.  }  

用法七:关于枚举集合的使用

java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。
关于枚举的实现细节和原理请参考:
参考资料:《ThinkingInJava》第四版
http://softbeta.iteye.com/blog/1185573

Java 枚举:switch 支持枚举demo

package mark.demo;
import java.util.Random;
public class EnumDemo {
public static void main(String[] args) {
                int len = Color.values().length;
                Color color = Color.getColor(len);
                switch (color) {
                case RED:
                        System.out.println("select " + "RED");
                        break;
                case GREEN:
                        System.out.println("select " + "GREEN");
                        break;
                case BLUE:
                        System.out.println("select " + "BLUE");
                        break;
                case YELLOW:
                        System.out.println("select " + "YELLOW");
                        break;
                default:
                        System.out.println("select " + "unknow!!");
                        break;
                }
        }
public enum Color {
                RED("red color", 0), 
                GREEN("green color", 1),
                BLUE("blue color", 2), 
                YELLOW("yellow color", 3);
Color(String name, int id) {
                        _name = name;
                        _id = id;
                }
private String _name;
                private int _id;
public String getName() {
                        return _name;
                }
public int getId() {
                        return _id;
                }
public static Color getColor(int max) {
                        Random random = new Random(System.currentTimeMillis());
                        int num = random.nextInt(max);
                        switch (num) {
                        case 0:
                                return Color.RED;
                        case 1:
                                return Color.GREEN;
                        case 2:
                                return Color.BLUE;
                        case 3:
                                return Color.YELLOW;
                        default:
                                return Color.BLUE;
                        }
                }
        }
}

枚举和静态常量的区别是什么

常量是直接编译在代码中的,而枚举则是一种类,你可以通过反射根据值反查出它的枚举形式是什么。
 
枚举定义了值的范围,但是常量没有。所以要根据你的实际情况选择。比如你有一个变量,是中国所有的省,那么最好用枚举,因为这些是固定不变的。在代码里使用的时候更方便,也易懂。
  
常量不是数据类型,只是说明被定义数据是不可变的常量还是可变变量;枚举是一种数据类型。

枚举定义了一组业务类型相同的成员且成员的语义清晰;常量也可以是一个基础类型的数组,比如int[],虽然业务类型那个上这些元素可能是一类的,但是没法清晰指出其中元素的意义。
 
枚举类是为了让自己更直接的知道 每个常量所代表的意义 同时也给该类型的变量一个取值的限制
 
定义一种枚举类型(就像int类型一样)后,声明的枚举类型变量(就像 int i;中的i),枚举类型变量的取值范围被限定为之前枚举类型中定义的值。常量就是不能变的量,如字符A,数字1,或者用const声明的不能再被赋值的变量。
 
枚举定义了一个变量的可使用范围。另外,能够是程序可读性提高。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值