java 枚举

本文介绍了Java中的枚举类型,包括枚举的定义、常用方法,以及Android系统源码中的枚举使用示例。枚举用于限定对象的取值范围,如季节、时钟样式等。在实际开发中,枚举可以用于定义视频尺寸和帧率等固定选项,便于管理和操作。枚举的name和ordinal属性提供了方便的比较和检索方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java 5引入了枚举,enum和class以及interface属于同级别的存在,我们在开发中使用类和接口比较多,使用枚举的情况比较少,下面介绍一下枚举。

枚举是将所有可能的情况一一列举出来,说明要描述的对象个数是有限的,例如:一年有12个月,一周有7天等。

1. java中枚举的定义

java中使用enum关键字定义枚举类,枚举类的实例对象要求一一罗列出来,对象间用“,”隔开,最后一个对象建议用“;”结束。可以有构造方法,必须是私有的,默认也是私有的,可以像其它类一样定义方法,成员变量,定义抽象方法的话枚举中定义的实例对象必须实现;通过enum定义的枚举类默认继承java.lang.Enum,且默认被final修饰,不能被继承,不过可以实现接口。

public enum SeasonEnum {
    SPRING, SUMMER, AUTUMN, WINTER;
}

上面是枚举最简单的用法,定义枚举类建议类名以Enum结尾,枚举实例对象全部用大写字母,多单词组合可以用下划线连接单词。

2. 枚举类常用的方法

Enum类中有两个比较重要的成员变量name和ordinal

name和ordinal的值是在Enum的构造方法中赋值的,然而该构造方法是由编译器调用,不是由我们手动调用。

/**
 * Sole constructor.  Programmers cannot invoke this constructor.
 * It is for use by code emitted by the compiler in response to
 * enum type declarations.
 *
 * @param name - The name of this enum constant, which is the identifier
 *               used to declare it.
 * @param ordinal - The ordinal of this enumeration constant (its position
 *         in the enum declaration, where the initial constant is assigned
 *         an ordinal of zero).
 */
protected Enum(String name, int ordinal) {
    this.name = name;
    this.ordinal = ordinal;
}

那么对于上面SeasonEnum定义的枚举,枚举实例的name和ordinal分别是什么呢?

public enum SeasonEnum {
    SPRING, SUMMER, AUTUMN, WINTER;
}

//对于春夏秋冬实例编译器通过下面的构造方法怎么创建呢?
protected Enum(String name, int ordinal) {
    this.name = name;
    this.ordinal = ordinal;
}

//name是实例的字符串名称,ordinal是从0开始依次+1
SPRING = new Enum("SPRING", 0);
SUMMER = new Enum("SUMMER", 1);
AUTUMN = new Enum("AUTUMN", 2);
WINTER = new Enum("WINTER", 3);

name()和ordinal()方法分别返回是name和ordinal的值,Enum的toString方法默认也是返回的name属性。compareTo方法比较的是两个枚举实例的ordinal差值。

还有一个编译器为我们生成的静态values()方法,返回我们定义的枚举实例对象的数组

SeasonEnum[] seasonEnums = SeasonEnum.values();
for (SeasonEnum seasonEnum : seasonEnums) {
    Log.e(TAG, "main: seasonEnum=" + seasonEnum);
}
//运行输出结果就是
SPRING
SUMMER
AUTUMN
WINTER

3. Android系统源码中枚举的使用

//时钟样式枚举,数字和表盘两种样式
//源码链接如下http://androidxref.com/9.0.0_r3/xref/packages/apps/DeskClock/src/com/android/deskclock/data/DataModel.java#55
/** Indicates the display style of clocks. */
public enum ClockStyle {ANALOG, DIGITAL}
    /**
     * The preferred starting day of the week can differ by locale. This enumerated value is used to
     * describe the preferred ordering.
     */
    public enum Order {
        SAT_TO_FRI(SATURDAY, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY),
        SUN_TO_SAT(SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY),
        MON_TO_SUN(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY);

        private final List<Integer> mCalendarDays;

        Order(Integer... calendarDays) {
            mCalendarDays = Arrays.asList(calendarDays);
        }

        public List<Integer> getCalendarDays() {
            return mCalendarDays;
        }
    }
    /**
     * 源码ImageView的缩放类型,android的老铁们肯定不陌生
     */
    public enum ScaleType {
        MATRIX      (0),
        FIT_XY      (1),
        FIT_START   (2),
        FIT_CENTER  (3),
        FIT_END     (4),
        CENTER      (5),
        CENTER_CROP (6),
        CENTER_INSIDE (7);

        ScaleType(int ni) {
            nativeInt = ni;
        }
        final int nativeInt;
    }

4. 模拟演练

上图是redmi k40相机录像模式中的功能,针对视频的尺寸和帧率这里用枚举实现一下(特别声明:本人不是小米红米员工,也没看过他们的代码,只是根据自己的理解来用枚举实现,如果有做过相机类似功能的大佬也欢迎提出正宗的方案)

public enum VideoSizeFPSEnum {
    VIDEO_720P_30FPS(1280, 720, 30),
    VIDEO_1080P_30FPS(1920, 1080, 30),
    VIDEO_1080P_60FPS(1920, 1080, 60),
    VIDEO_4K_30FPS(3840, 2160, 30);
    private final int videoWidth;
    private final int videoHeight;
    private final int videoFPS;

    VideoSizeFPSEnum(int videoWidth, int videoHeight, int videoFPS) {
        this.videoWidth = videoWidth;
        this.videoHeight = videoHeight;
        this.videoFPS = videoFPS;
    }

    public int getVideoWidth() {
        return videoWidth;
    }

    public int getVideoHeight() {
        return videoHeight;
    }

    public int getVideoFPS() {
        return videoFPS;
    }
}
//根据业务逻辑用枚举可能会写类似这样的代码
private void switchVideoSizeFPS(VideoSizeFPSEnum videoSizeFPSEnum) {
    switch (videoSizeFPSEnum) {
        case VIDEO_720P_30FPS:
            //保存状态建议保存name值,videoSizeFPSEnum.name();
            //省略切换尺寸相关逻辑...
            break;
        case VIDEO_1080P_30FPS:
            break;
        case VIDEO_1080P_60FPS:
            break;
        case VIDEO_4K_30FPS:
            break;
    }
}
private VideoSizeFPSEnum getUserVideoSizeFPS() {
    //假设我们拿到了上次保存的name值为 videoSizeFPSName
    String videoSizeFPSName = "上次保存的name值";
    //有了name值我们可以直接得到对应的枚举对象,这也是为什么推荐保存name的原因
    //不过也要考虑枚举实例变动或者是保存的name值被串改的情况,name不匹配会抛出异常
    VideoSizeFPSEnum videoSizeFPSEnum = VideoSizeFPSEnum.valueOf(videoSizeFPSName);
    return videoSizeFPSEnum;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值