建議速讀 | Java 常量定義的正確姿式✈!

本文由 yanglbme 原創,首發於公衆號「Doocs開源社區」,禁止未受權轉載。java

在 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開源社區」,原創技術文章第一時間推送。

相關文章
相關標籤/搜索