• Java枚举的小知识点


    enum 是jdk1.5引入的,使用它可以创建枚举类型,就像使用class创建类一样。

    enum关键字创建的枚举类型默认是java.lang.Enum(一个抽象类)的子类

    用法1 常量

    一般定义常量都是 public static final …,现在可以把相关常量都放在一个枚举类里,而且枚举比常量提供更多方法

    1. enum season{
    2.    Spring,Summer,Autumn,Winter
    3. }

    用法2 switch jdk1.6之前只支持int,char,enum类型,使用enum,提高代码可读性

    1. enum season{
    2.    Spring,Summer,Autumn,Winter
    3. }
    4. public class SeasonEnum {
    5.    public static void main(String [] args) {
    6.       season current_season=season.Autumn;
    7.       switch(current_season) {
    8.       case Spring:System.out.println("当前季节是"+current_season+" 竹外桃花三两枝,春江水暖鸭先知");break;
    9.       case Summer:System.out.println("当前季节是"+current_season+" 接天莲叶无穷碧,映日荷花别样红");break;
    10.       case Autumn:System.out.println("当前季节是"+current_season+" 停车做外枫林晚,霜叶红于二月花");break;
    11.       case Winter:System.out.println("当前季节是"+current_season+" 忽如一夜出风来,千树万树梨花开");break;
    12.       }
    13.    }
    14. }

    用法3 向枚举类中添加新方法 如果打算自己定义方法,必须在enum实例序列最后添加一个分号,而且必须先定义enum实例。

    用法4 覆盖枚举的方法

    1. public enum CarInfoEnum {
    2.    dongfeng("东风",15.8),
    3.    benchi("奔驰",25.0),
    4.    yiqi("一汽",18.5),
    5.    baoma("宝马",35.7),
    6.    xuelai("雪莱",100.5),
    7.    ;
    8.  
    9.    /**
    10.     * enum的构造方法要么是private ,要么是默认(默认私有),prtected和public都不行
    11.     * @param name
    12.     * @param price
    13.     */
    14.    CarInfoEnum(String name,Double price) {
    15.       this.name=name;
    16.       this.price= price;
    17.    }
    18.  
    19.    private String name;
    20.    private Double price;
    21.  
    22.    public String getName() {
    23.       return name;
    24.    }
    25.    public void setName(String name) {
    26.       this.name = name;
    27.    }
    28.    public Double getPrice() {
    29.       return price;
    30.    }
    31.    public void setPrice(Double price) {
    32.       this.price = price;
    33.    }
    34.  
    35.    @Override
    36.    public String toString() {
    37.       return "名称:"+this.getName()+" 价格:"+this.getPrice();
    38.    }
    39.  
    40.    public static void main(String [] args) {
    41.       //获取枚举对象
    42.       CarInfoEnum carEnum =CarInfoEnum.valueOf("dongfeng");
    43.       System.out.println(carEnum.toString());
    44.  
    45.       //枚举遍历 方法1 使用java8新特性 方法引用、lambda表达式、Stream流
    46.       CarInfoEnum[] cars= CarInfoEnum.values();
    47.       Stream.of(cars).forEach(System.out::println);
    48.  
    49.       //枚举遍历 方法2 增强for
    50.       for(CarInfoEnum car :CarInfoEnum.values()) {
    51.          System.out.println(car);
    52.       }
    53.    }
    54.  
    55. }

    用法5 实现接口 所有枚举都继承自java.lang.Enum类,java类单继承,接口多继承,枚举对象可以实现多个接口。

     

    用法6 使用接口组织枚举

    1.  /*@description 使用接口组织枚举 对一组数据分类,食物菜单分类而且希望这些菜单都属于food类型,如mainCourse主菜,fruit水果 drink 饮品
    2.  *每种分类下有多种具体的菜式或食品,此时可以利用接口组织
    3. */
    4. public interface Food {
    5.    enum mainCourse implements Food{
    6.       RICE,NOODLES,DUMPLING,CHINKEN,BEEF;
    7.    }
    8.  
    9.    enum fruit implements Food{
    10.       BANANA,APPLE,ORANGE,PEAR;
    11.    }
    12.  
    13.    enum drink implements Food{
    14.       TEA, MILK,COFFEE,GREEN_TEA,RED_TEA;
    15.    }
    16. }
    17. public class TypeOfFood {
    18.  
    19.    public static void main(String [] args) {
    20.       Food food=mainCourse.BEEF;
    21.       System.out.println(food);
    22.       food=fruit.APPLE;
    23.       food=drink.COFFEE;
    24.    }
    25.  
    26. }

    用法7 单例模式 由于枚举的构造默认是私有的,而且编译器jvm不允许使用反射机制创建枚举实例,因此使用枚举创建单例是非常安全,但是占用内存较大

    1. public enum SingletonEnum {
    2.    INSTANCE,
    3.    ;
    4.    private String name; //该单例拥有的属性定义
    5.  
    6.    public String getName() {
    7.       return name;
    8.    }
    9.  
    10.    public void setName(String name) {
    11.       this.name=name;
    12.    }
    13. }

    源码分析理解为什么枚举可以创建单例模式

    枚举单例,使用SingletonEnum.INSTANCE进行访问,避免调用getInstance方法,完全不用考虑序列化和反射的问题。枚举序列化由jvm保证,每一个枚举类型和定义的枚举变量在jvm中唯一,在枚举类型序列化和反序列化上,java做如下规定:在序列化时java仅仅是将枚举对象的那么属性输出到结果,反序列化则是通过Enum的valueOf方法来根据名字查找枚举对象。同时编译器是不允许任何对这种序列化机制的定制的,并禁用了redObject,readObjectNoData,writeObject等,从而保证枚举实例唯一性。看一下Enum类的valueOf方法

    1. public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
    2.       //调用enumType(Class对象的引用)的enumConstantDirectory方法获取到一个Map集合,该集合存放key(枚举name为key)--à value(枚举实例变量为value)对
    3.  T result = enumType.enumConstantDirectory().get(name);
    4.        if (result != null)
    5.            return result;
    6.        if (name == null)
    7.            throw new NullPointerException("Name is null");
    8.        throw new IllegalArgumentException(
    9.            "No enum constant " + enumType.getCanonicalName() + "." + name);
    10.    }

    我们看一下Class类的enumConstantDirecotry方法

    1. Map<String, T> enumConstantDirectory() {
    2.         if (enumConstantDirectory == null) {
    3. //getEnumConstantsShared最终通过反射调用枚举类的values方法
    4.             T[] universe = getEnumConstantsShared();
    5.             if (universe == null)
    6.                 throw new IllegalArgumentException(
    7.                     getName() + " is not an enum type");
    8.             Map<String, T> m = new HashMap<>(2 * universe.length);
    9. //map存放了当前enum类的所有没举实例变量,以name为key值
    10.             for (T constant : universe)
    11.                 m.put(((Enum<?>)constant).name(), constant);
    12.             enumConstantDirectory = m;
    13.         }
    14.         return enumConstantDirectory;
    15.     }

     

  • 相关阅读:
    关于 Wordpress安装时出现“Warning: Cannot modify header information – headers already sent by….”
    C#、.Net经典面试题集锦(二)
    .net 中的事务总结
    什么是webservice
    Web Service与 .NET Remoting
    动态语句exec与sp_executesql执行计划区别
    SQL2005以上版本派生表更新
    清理sql server 2005 服务器名称列表
    如何卸载VS2008
    [怎樣處理]SQL2008、SQL2005類型判斷出錯
  • 原文地址:https://www.cnblogs.com/gaochaochao/p/9919295.html
Copyright © 2020-2023  润新知