java枚举

*爱你&永不变心* 提交于 2019-11-28 11:30:38

1、为何使用Java枚举


Java5之前没有enum的情况下,我们一般使用几个int常量表示枚举值(int枚举类型)或者string枚举类型

public static final ZOO_CAT=1 #表示小猫

public static final ZOO_CAT=2 #表示小狗

作为方法参数zooType是int类型

如 public void printZoo(int zooType){

}

 

这样的话 我们调用方法只要是int类型就行 ,没法控制方法调用的安全性

其次 作为一个数字 如果打印到日志是个裸数字没有可读性

为此 java5 产生了enum 固定且有限的类型都可以使用enum。

 

2、如何使用java枚举


 

package com.yangfei.test.meiju;

public class EnumYf {
    enum ZOO{
        CAT,DOG,PIG
    }

    public static void printZoo(ZOO zooType){
        System.out.println("my name is " + zooType);
    }

    public static void main(String[] args){
        printZoo(ZOO.DOG);
    }
}
View Code

如上 一个简单的例子 EnumYf中定义了一个动作枚举类型。

当一个枚举是公共的分类时 我们应该定义单独的文件定义,如:

public enum xxx{

  x1,x2,x3

}

 

3、枚举实际就是类


3.1 枚举就是一个类

定义一个enum

package com.yangfei.test.meiju;

public class EnumYf {
    enum ZOO{
        CAT,DOG,PIG
    }

    public static void printZoo(ZOO zooType){
        System.out.println("my name is " + zooType);
    }

    public static void main(String[] args){
        printZoo(ZOO.DOG);
        System.out.println(ZooEnum.CAT);
    }
}
View Code

 

对编译生成的class文件 使用javap -p -c xx.class查看生成的字节码文件:

可以看到:

  •  enum编译后 实际生成了一个class ,此类是final的且继承抽象类Enum
  • 构造方法时private 表面枚举是没法外部在new一个新对象的
  • 枚举值实际就是当前类的几个常量实例

 

所以我们使用枚举是没法再继承其他类的,但可以实现接口。

 

3.2 我们再看看Enum抽象类的结构

 

实现了Comparable和Serializable接口 表面Enum是有内在的排序和可序列化的

 

 我们看几个方法:

a. compareTo方法

 

public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }

  compareTo实际比较的是ordinal

b. ordinal方法

   直接返回ordinal属性值 这个值表示在enum中枚举值的定义顺序 从0开始。

  看java源码说明。一般用在EnumSet和EnumMap中 ,外部不要轻易使用ordinal(万一枚举定义顺序变了咋办!)

 

/**
     * The ordinal of this enumeration constant (its position
     * in the enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     *
     * Most programmers will have no use for this field.  It is designed
     * for use by sophisticated enum-based data structures, such as
     * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     */
    private final int ordinal;

 

 

4、枚举常用场景


 

4.1 values方法 

   values方法会返回所有的枚举实例,数组类型。

   这个方法不是Enum类中的方法,是编译器编译中自动添加的方法。如下所示:

 

 

4.2 作为方法的入参

    如:

public class EnumYf {
    public static void printZoo(ZooEnum zooEnum){
        System.out.println(zooEnum.name());
    }
    public static void main(String[] args){
        printZoo(ZooEnum.DOG);
    }
}
View Code

 

4.3 switch判断

public class EnumYf {
    public static void printZoo(ZooEnum zooEnum){
        switch (zooEnum){
            case DOG:
                System.out.println("this is dog");
                break;
            case CAT:
                System.out.println("this is cat");
                break;
            case PIG:
                System.out.println("this is pig");
                break;
        }
    }
    public static void main(String[] args){
        printZoo(ZooEnum.DOG);
    }
}
View Code

 

 

5、枚举的序列化


枚举是可序列化的 

但枚举的序列化比较特殊,序列化时只会将枚举的name(就是一字符串)序列化

反序列时 根据枚举的valueOf(String name)找到对应的枚举常量,也就是说即使反序列化也不会生成新的实例

这点对单例模式就有绝对的保护 ,单例默认参考博主另一篇博文:https://www.cnblogs.com/yangfei629/p/11370732.html

 

6、特定于常量的方法实现

 TODO

7、枚举实现接口

 TODO

8、EnumSet和EnumMap

TODO

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!