在 Java 中,关于常量的话题彷佛有不少困惑。有些人使用整数或字符串来定义常量,而另外一些人则使用枚举。我还遇到了在其本身的接口中定义的常量,使用该常量的类必须实现该接口。这种策略一般称为接口常量设计模式。git
在这篇文章里,我会介绍在 Java 中存储常量的两种最多见的策略:整数和枚举。首先,不管什么时候决定使用常量,都应确保常量不会随时间变化,所以能够避免从新编译。github
咱们选用一个很是常见的关于常量的例子:Weekday
。设计模式
假定咱们在线商店中有一个表明订单 Order 的类,咱们但愿在其中跟踪订单在一周的哪一天发生。微信
咱们的类看起来像这样:函数
public class Order {
private [datatype] weekDay;
public [datatype] getWeekDay() {
return weekDay;
}
public void setWeekDay([datatype] weekDay) {
this.weekDay = weekDay;
}
}
复制代码
请注意,该类暂时没法编译,datatype
只是咱们将要使用的常量类型的占位符。this
在 Java 中定义常量的最多见方法之一是使用整数,其中整数变量使用 static final
修饰。spa
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;
复制代码
定义整数常量时,咱们要考虑的第一个问题是将它们放在哪里。设计
咱们是否将它们直接放置在 Order 类中?仍是咱们将它们放在一个单独的类中。调试
因为 Weekday 不必定只应用到 Order 类型的对象中,所以咱们在一个单独的类 Weekday 中定义它们。
public class WeekDay {
private WeekDay() {}
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;
}
复制代码
你可能注意到了私有构造函数,这是为了不客户端实例化该类。该类仅包含不与对象绑定的静态变量,所以无需实例化该类。
如今,每当须要为 Order 设置特定的日期时,咱们能够这样操做:
Order order = new Order();
order.setWeekDay(WeekDay.MONDAY);
复制代码
当咱们要检查订单是否在星期五发生时,咱们能够简单地调用 getter 方法:
if (order.getWeekDay() == WeekDay.FRIDAY) {}
复制代码
到目前为止,一切都很好。这种设计看起来彷佛没有任何问题。
好吧,假设你在一年后再次回到此代码,而且你必须检查是否在星期一下订单。你可能彻底忘记了 Weekday 这个类(不排除这种可能)...
在这种状况下,你能够尝试以下操做:
if (order.getWeekDay() == 1) {}
复制代码
彻底忘记了 WeekDay 类,此代码很是合理。星期一是一周的第一天,因此工做日应该是 1,对吗?可是不,不是,由于在咱们的 Weekday 类中静态 int 变量 Monday 被定义为 0!
这是为何你应该考虑避免使用整数常量的一个很好的例子。它们容易出错,混乱而且难以调试。
在 Java 中定义常量的另外一种方法是使用枚举。
使用枚举时,常量类将以下所示:
public enum WeekDay {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
复制代码
请注意,这里没有私有构造函数,你也无需强制该类是不可实例化的,由于默认状况下枚举是不可实例化的!
给 Order 设置 WeekDay 的语法与使用整数常量的语法彻底相同:
order.setWeekDay(WeekDay.MONDAY);
复制代码
咱们是否能够在星期五处理订单方面也没有区别:
if (order.getWeekDay() == WeekDay.FRIDAY) {}
复制代码
可是,主要区别在于:这是你能够在 Order 类中设置和比较 weekday 变量的值的惟一方法。
若你使用 order.setWeekDay(1);
和 if(order.getWeekDay()== 1)
,将使编译器抛出错误,由于当你尝试使用整型类型的变量时,它们应为 WeekDay 类型!
回想一下你彻底忘记了 “WeekDay” 常量类的状况。对于枚举,这再也不是问题!若是你尝试使用整数代替 WeekDay 枚举的成员,则编译器将简单地引起一个错误,告诉你须要使用 WeekDay 枚举。
换句话说,检查订单是否在星期五发生的惟一方式是:
if (order.getWeekDay() == WeekDay.FRIDAY) {}
复制代码
你再也不须要记住常数类,并且若是有任何客户端要使用你的代码,则没必要怀疑星期一其实是用 0 仍是 1 表示。
我但愿这个例子能够清楚地展现为何在定义常量时应该考虑对整数使用枚举。枚举将使咱们的代码不易出错,更易于阅读,而且更易于维护!
最后,推荐阅读《Effective Java 第3版[2019]》这本好书。
我是 GitHub 技术社区 Doocs 发起人,欢迎关注个人微信公众号“Doocs开源社区”,原创技术文章第一时间推送。