Java高级系列——枚举(Enums)

一、介绍

枚举的思想很简单,也很方便:它代表了一组固定的常量值。实际开发应用中,枚举经常用来设计一些状态常量。

比如,星期几就是枚举的一个最好例子,因为他们被限制在周一、周二、周三、周四、周五、 周六和周日。

二、枚举是一种特殊的类

在枚举被引入Java语言之前,在Java中模拟一组固定值的常规方法是通过声明一组常量。例如:

public class DaysOfTheWeekConstants {
    public static final int MONDAY = 0;
    public static final int TUESDAY = 1;
    public static final int WEDNESDAY = 2;
    public static final int THURSDAY = 3;
    public static final int FRIDAY = 4;
    public static final int SATURDAY = 5;
    public static final int SUNDAY = 6;
}

虽然这种方法有效,但远非理想的解决方案。视觉上太多太麻烦。

虽然这种方法有效,但远非理想的解决方案。主要是因为常量本身只是int类型的值,而代码中需要这些常量(而不是任意的int值)的每一个地方都应该被一直明确地记录和断言。从语义上来讲,比如下面的这个方法演示所表现出来的就不符合类型安全的概念:

public boolean isWeekend( int day ) {
    return( day == SATURDAY || day == SUNDAY );
}

从逻辑角度去看,day参数应该是在DaysOfTheWeekConstants类中声明的值之一。然而,如果没有编写额外的说明文档(给后来的一些人阅读),就不可能猜测到这一点,所以不便于维护。当然了,对于Java编译器来说类似于isWeekend(100)的这种调用看起来完全是正确的并且不会引起任何顾虑,所以不会好心提醒你。

此时枚举就能解决这些问题。枚举允许用类型化的值替换常量并在任何地方使用这些类型。让我们使用枚举重写上面的方案。

public enum DaysOfTheWeek {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

这里将关键字class改成了enum并且这些可能的值在枚举定义时被列举出来。有区别的一部分就是被声明在枚举类(在我们的例子中是DaysOfTheWeek )中的每一个单独的值都是一个实例。因此,每当枚举被使用,Java编译器都能够进行类型检查。比如:

public boolean isWeekend(DaysOfTheWeek day) {
    return(day == SATURDAY || day == SUNDAY);
}

请注意枚举中的大写命名法的使用是一个约定,但是如果你不这样做也没有谁能够阻止你,但是最好还是遵守约定,这样更有利于代码的维护。

三、枚举与实例字段(Enums and instance fields)

枚举是一个特殊的类,所以它是可拓展的,所以他们可以有实例字段构造器方法

(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须private修饰!!!)。

(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须private修饰!!!)。

(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须private修饰!!!)。

让我们使用枚举的实例和构造器添加一个isWeekend属性。

public enum DaysOfTheWeekFields {
    MONDAY(false),
    TUESDAY(false),
    WEDNESDAY(false),
    THURSDAY(false),
    FRIDAY(false),
    SATURDAY(true),
    SUNDAY(true);

    private final boolean isWeekend;

    private DaysOfTheWeekFields( final boolean isWeekend ) {
        this.isWeekend = isWeekend;
    }

    public boolean isWeekend() {
        return isWeekend;
    }
}

如上述代码中我们看到的,枚举值只是简单的调用了构造器而并没有要求使用new关键字。isWeekend()方法可以用来确定是否枚举值代表工作日或者周末(即是否生效)。如下:

public boolean isWeekend( DaysOfTheWeek day ) {
    return day.isWeekend();
}

四、枚举与接口(Enums and interfaces)

另外一个强大的特性,我们可以通过实现接口,再次确认了一下枚举确实是一个特殊的类,因为它能够实现接口(然而枚举不能够继承任何类,第“五”节讲)。比如,让我们引入接口DayOfWeek。

interface DayOfWeek {
    boolean isWeekend();
}

然后合并实例字段和接口实现的枚举例子如下:

public enum DaysOfTheWeekFieldsInterfaces implements DayOfWeek {
    MONDAY( false ),
    TUESDAY( false ),
    WEDNESDAY( false ),
    THURSDAY( false ),
    FRIDAY( false ),
    SATURDAY( true ),
    SUNDAY( true );

    private final boolean isWeekend;

    private DaysOfTheWeekFieldsInterfaces(final boolean isWeekend){
        this.isWeekend = isWeekend;
    }

    @Override
    public boolean isWeekend() {
        return isWeekend;
    }
}

五、枚举与泛型

在Java中,虽然咋一看并看不出来枚举和泛型的关系,但是他们之间存在一种关系。Java中的每一个单独的枚举自动继承自泛型类Enum<T>,在这里T就是枚举类型本身。Java编译器在编译时帮忙替代开发者做了这个转换,拓展一下枚举声明public enum DaysOfTheWeek 如下:

public class DaysOfTheWeek extends Enum< DaysOfTheWeek > {
    // Other declarations here
}

这也就说明了为什么枚举可以实现接口但不能继承其他类:因为它隐式的继承Enum<T>并且我们在使用对象的公共方法时已经讨论过,Java中不支持多继承

 

节选自:https://blog.csdn.net/zyhlwzy/article/details/79045066,不常用的部分就没复制过来,感兴趣的可以去原博客看看。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值