枚举

来源:互联网 发布:小说书籍知乎 编辑:程序博客网 时间:2024/06/14 05:53

不要让这个世界的复杂性阻碍你的前进。 要成为一个行动主义者,将解决人类的不平等视为己任。 它将成为你生命中最重要的经历之一。
——比尔·盖茨在哈佛大学的演讲

声明枚举

[public]enum 枚举类型名称[implements 接口名称列表]{    枚举值;    变量成员声明及初始化;    方法声明及方法体;}

简单的例子:

/** * 简单的枚举类型举例 * @author wangbaofu *  */public class ScoreTester {    public static void main(String[] args) {        giveScore(Score.EXCELLENT);    }    private static void giveScore(Score s) {        switch (s) {        case EXCELLENT:            System.out.println("Excellent");            break;        case QUALIFIED:            System.out.println("Qualified");            break;        case FAILED:            System.out.println("Failed");            break;        default:            break;        }    }}enum Score {    EXCELLENT, QUALIFIED, FAILED;}/* * 输出 Excellent * */

枚举的特点:

  • 枚举定义实际上是定义了一个类
  • 所有枚举类型都隐含继承(扩展)自Java.lang.Enum,因此枚举类型不能再继承任何其它类
  • 枚举类型中的类可以包括方法和变量
  • 枚举类型的构造方法必须是包内私有或者私有的。定义在枚举开头的常量会自动创建,不能显示地调用枚举类的构造方法。

枚举类型的默认方法

  • 静态的values()方法用于获得枚举类型的枚举值的数组
  • toString方法返回枚举值的字符串描述
  • valueOf方法将以字符串形式表示的枚举值转化为枚举类型的对象
  • Ordinal方法获得对象在枚举类型中的位置索引

最佳实践 (该部分内容为《编写高质量代码之java》学习笔记)

推荐使用枚举定义常量

常量声明是每一个项目都不可或缺的,在Java 1.5之前,
我们只有两种方式的声明:类常量和接口常量,若在项目中
使用的是Java 1.5之前的版本基本上都是如此定义的。不过,
在1.5版以后有了改进,即新增了一种常量声明方式: 枚举声明常量
枚举声明常量的优点
(1)枚举常量更简单
(2)枚举常量属于稳态型
(3)枚举具有内置方法
是java.lang.Enum的子类,该基类提供了诸如获得排序值的ordinal方法、compareTo比较方法等,大大简化了常量的访问。
(4)枚举可以自定义方法
举常量不仅可以定义静态方法,还可以定义非静态方法,而且还能够从根本上杜绝常量类被实例化。

    package enumtest;/** * 枚举的优势 * */public class TestSeason {    public static void main(String[] args) {//      通过values方法获得所有的枚举项        for (Season s : Season.values()) {            System.out.println(s);        }    }}enum Season{    Spring,Summer,Autumn,Winter;}interface SeasonIntece{    int Spring=0;    int Summer=1;    int Autumn=2;    int Winter=3;}

使用构造函数协助描述枚举项

枚举的属性:排序号,其默认值为0,1,2,3…
枚举描述:含义通过枚举的构造函数,声明每个枚举项(也就是枚举的实例)
必须具有属性和行为,这是对枚举的描述和补充,目的是使,枚举项表述的意义更加清晰准确

    enum Season {    Spring("春"), Summer("夏"), Autumn("秋"), Winter("冬");
    private String desc;    Season(String desc) {        this.desc = desc;    }    // 自定义方法    public static Season getComfortableSeason() {        return Spring;    }//获取枚举描述    public String getDesc() {        return desc;    }}   

小心switch带来的空值异常,处理方法增加空判断

对于枚举类型很多的情况下,在default中添加: throw
new AssertionError(“没有该类型”);

使用valueOf前必须进行校验

    package enumtest;import java.util.Arrays;import java.util.List;public class ValueOfTest {    public static void main(String[] args) {        List<String> params = Arrays.asList("EXCELLENT", "aDD");        for (String name : params) {            // 查找直面值与name相同的枚举 项//          添加代码            if(Score.contains(name)){                Score s = Score.valueOf(name);                if (s != null) {                    // 有该枚举项时                    System.out.println(s);                } else {                    // 没有该枚举项时                    System.out.println("无相关枚举项");                }            }            //          Score s = Score.valueOf(name);//          if (s != null) {//              // 有该枚举项时//              System.out.println(s);//          } else {//              // 没有该枚举项时//              System.out.println("无相关枚举项");//          }        }    }    enum Score {        EXCELLENT, QUALIFIED, FAILED, ADD;        // 是否包含枚举项        public static boolean contains(String name) {            // 所有的枚举值            Score[] scores = values();            // 遍历查找            for (Score s : scores) {                if (s.name().equals(name))                    return true;            }            return false;        }    }}/* * Exception in thread "main" java.lang.IllegalArgumentException: No enum * constant enumtest.ValueOfTest.Score.aDD *  * public static<T extends Enum<T>>T valueOf(Class<T>enumType, String name){ * //通过反射,从常量列表中查找 T result=enumType.enumConstantDirectory().get(name); * if(result!=nullreturn result; if(name==null) throw new * NullPointerException("Name is null"); //最后排除无效参数异常 throw new * IllegalArgumentException("No enum const"+enumType+"."+name); } */

(1) 枚举非静态方法实现工厂方法模式
用枚举实现工厂方法模式更简洁

package enumtest;/** * 工厂方法模式(Factory Method Pattern)是“创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类”。 * 工厂方法模式在我们的开发工作中经常会用到。 * 这是最原始的工厂方法模式,有两个产品:福特汽车和别克汽车,然后通过工厂方法模式来生产。有了工厂方法模式,我们就不用关心一辆车具体是怎么生成的了 * ,只要告诉工厂“给我生产一辆福特汽车”就可以了 */// 抽象产品interface Car {};// 具体产品类class FordCar implements Car {};// 具体产品类class BuickCar implements Car {};// 工厂类public class CarFactory {    public static Car createCar(Class<? extends Car> c) {        try {            return c.newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }        return null;    }    public static void main(String[] args) {//      生产车辆        Car cat =CarFactory.createCar(FordCar.class);    }}
package enumtest;//枚举非静态方法实现工厂方法模式public class CarFactoryEnum {    public static void main(String[] args) {//      生产汽车        Car car = CarFactoryEnum1.BuickCar.create();    }}enum CarFactoryEnum1 {    // 定义工厂类能生产汽车的类型    FordCar, BuickCar;    // 生产汽车    public Car create() {        switch (this) {        case FordCar:            return new FordCar();        case BuickCar:            return new BuickCar();        default:            throw new AssertionError("无效参数");        }    }}

(2)通过抽象方法生成产品

enum CarFactory3{    FordCar{        public Car create(){            return new FordCar();        }    },BuickCar{        public Car create(){            return new BuickCar();        }    };//  首先定义一个抽象制造方法create,然后每个枚举项自行实现。    public abstract Car create();}

用枚举类型的工厂方法模式有以下三个优点:
(1)避免错误调用的发生
(2)性能好,使用便捷
枚举类型的计算是以int类型的计算为基础的,这是最基本的操作,性能当
然会快,至于使用便捷,注意看客户端的调用,代码的字面意思就是“汽车
工厂,我要一辆别克汽车,赶快生产”。
(3)降低类间耦合
不管生产方法接收的是Class、String还是int的参数,都会成为客户端类的
负担,这些类并不是客户端需要的,而是因为工厂方法的限制必须输入的,
例如Class参数,对客户端main方法来说,它需要传递一个FordCar.class
参数才能生产一辆福特汽车,除了在create方法中传递该参数外,业务类
不需要改Car的实现类。这严重违背了迪米特原则(Law of Demeter,简称为LoD),也就是最少知识原则:一个对象应该对其他对象有最少的了解。
示例代码

    /**     * 支付类型     */    public enum PayType{        typeUnknow("未知支付类型" , -1), typeAlipay("支付宝支付" , 4), typeWechatPay("微信支付" , 5);        private String name;        private int value;        // 构造方法        private PayType(String name, int value) {            this.name = name;            this.value = value;        }    }
0 0
原创粉丝点击