JAVA枚举类型和常量类的通俗解释

JAVA枚举类型和常量类的通俗解释

    • 背景
    • 问题
    • Java枚举特点
    • 总结
    • 用法
      • 用法一:常量
      • 用法二:switch
      • 用法三:向枚举中添加新方法
      • 用法四:覆盖枚举的方法
      • 用法五:实现接口
      • 用法六:使用接口组织枚举

背景

在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量的类。我们通常利用public final static 方法定义的代码如下,采用定义常量来调用自己想得到的变量

    public static final int SPRING  =1; //春天
    public static final int SUMMER  = 2; //夏天
    public static final int AUTUMN  = 3; //秋天
    public static final int WINTER  = 4; //冬天

问题

这种方法称作int枚举模式。可这种模式有什么问题呢,我们都用了那么久了,应该没问题的。通常我们写出来的代码都会考虑它的安全性、易用性和可读性。 首先我们来考虑一下它的类型安全性。当然这种模式不是类型安全的,比如说我们设计一个函数,要求传入春夏秋冬的某个值。但是使用int类型,我们无法保证传入的值为合法。

首先我们先了解下为什么Java要这样定义Enum

  1. 这里先定义枚举类型
enum Color{
    RED,GREEN,YELLOW
}
enum Season{
    SPRING,SUMMER,WINTER
}
public class EnumTest{
    public static void main(String[] args) {
        System.out.println(Color.RED.ordinal());
        System.out.println(Season.SPRING.ordinal());
    }
}
  1. 代码中两处输出内容都是 0 ,因为枚举类型的默认的序号都是从零开始的。
    要理解这个问题,首先我们来看一个Enum类中的方法(暂时忽略其他成员变量和方法)
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
        private final int ordinal;

        public final int compareTo(E o) {
        Enum other = (Enum)o;
        Enum self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }
}
  1. 首先我们认为Enum的定义中没有使用Enum,那么compareTo方法就要这样定义(因为没有使用泛型,所以就要使用Object,这也是Java中很多方法常用的方式)
public final int compareTo(Object o) 
  1. 当我们调用compareTo方法的时候依然传入两个枚举类型,在compareTo方法的实现中,比较两个枚举的过程是先将参数转化成Enum类型,然后再比较他们的序号是否相等。那么我们这样比较:
Color.RED.compareTo(Color.RED);
Color.RED.compareTo(Season.SPRING);
  1. 如果在compareTo方法中不做任何处理的话,那么以上这段代码返回内容将都是true(因为Season.SPRING的序号和Color.RED的序号都是 0 )。但是,很明显, Color.RED和Season.SPRING并不相等。
    但是Java使用Enum声明Enum,并且在compareTo的中使用E作为参数来避免了这种问题。 以上两个条件限制Color.RED只能和Color定义出来的枚举进行比较,当我们试图使用Color.RED.compareTo(Season.SPRING);这样的代码时,会报出这样的错误:
The method compareTo(Color) in the type Enum<Color> is not applicable for the arguments (Season)
  1. 他说明,compareTo方法只接受Enum类型。
    Java为了限定形态参数实例化的对象,故要求只能是Enum,这样才能对 compareTo之类的方法所传入的参数进行形态检查。 因为“红色”只有和“绿色”比较才有意义,用“红色”和“春天”比较毫无意义,所以,Java用这种方式一劳永逸的保证像compareTo这样的方法可以正常的使用而不用考虑类型。枚举的优点这时候就显示了出来

Java枚举特点

  • 使用关键字enum;
  • 类型名称,比如这里的Season;
  • 一串允许的值,比如上面定义的春夏秋冬四季;
  • 枚举可以单独定义在一个文件中,也可以嵌在其它Java类中;

除了这样的基本要求外,用户还有一些其他选择:

  • 枚举可以实现一个或多个接口(Interface);
  • 可以定义新的变量;
  • 可以定义新的方法;
  • 可以定义根据具体枚举值而相异的类。

总结

那么什么时候应该使用枚举呢?每当需要一组固定的常量的时候,如一周的天数、一年四季等。或者是在我们编译前就知道其包含的所有值的集合。Java 1.5的枚举能满足绝大部分程序员的要求的,它的简明,易用的特点是很突出的。

用法

用法一:常量

public enum Color {  
  RED, GREEN, BLANK, YELLOW  
}

用法二:switch

enum Signal {  
    GREEN, YELLOW, RED  
}  
public class TrafficLight {  
    Signal color = Signal.RED;  
    public void change() {  
        switch (color) {  
        case RED:  
            color = Signal.GREEN;  
            break;  
        case YELLOW:  
            color = Signal.RED;  
            break;  
        case GREEN:  
            color = Signal.YELLOW;  
            break;  
        }  
    }  
}  

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

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index;  
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    // 普通方法  
    public static String getName(int index) {  
        for (Color c : Color.values()) {  
            if (c.getIndex() == index) {  
                return c.name;  
            }  
        }  
        return null;  
    }  
    // get set 方法  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getIndex() {  
        return index;  
    }  
    public void setIndex(int index) {  
        this.index = index;  
    }  
}  

用法四:覆盖枚举的方法

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index;  
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    //覆盖方法  
    @Override  
    public String toString() {  
        return this.index+"_"+this.name;  
    }  
}

用法五:实现接口

public interface Behaviour {  
    void print();  
    String getInfo();  
}  

public enum Color implements Behaviour{  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index;  
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  

    //接口方法  
    @Override  
    public String getInfo() {  
        return this.name;  
    }  

    //接口方法  
    @Override  
    public void print() {  
        System.out.println(this.index+":"+this.name);  
    }  
}  

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

public interface Food {  
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}

参考文章:Java的枚举类型用法介绍
如有写的不对的地方,欢迎大家指导改正

你可能感兴趣的:(java,spring,开发语言,后端,spring,boot)