1. 程式人生 > >靜態變數、列舉、以及靜態程式碼塊的使用場景

靜態變數、列舉、以及靜態程式碼塊的使用場景

摘要: 靜態變數、列舉、以及靜態程式碼塊的使用場景

    記得最開始寫程式碼的時候,當使用到字串的時候,就在使用的 地方定義一個String型別的字串,但是後面發現在一個類中定義了很多重複的字串【最初的階段】。

    在sonar分析的時候,sonar建議把一個型別重複的字串提到最上面,定義成常量來使用。後來一段時間都是這麼做的。【稍有進步】

    後來,漸漸的發現其實不光是一個類的內部有重複的字串,相鄰的類中也有重複的字串的情況。然後就把這些字串定義到一個基類中,以業務為單位,每個業務都定義一個基類,把這些常量放到基類中,包括一些以業務為邊界的公共方法,也放到基類中。然後每個業務類都繼承該業務的基類。【這個是我跟一個有幾年經驗的前輩學習到的,算是一種進階的處理方法】

    隨後,我發現還有一些常量和方法是整個專案的公共方法,並不是以業務為邊界,可以再作為一個基類提出來的。但是java是單繼承的。不能繼承多個基類的。然後我就在業務基類的上方,再提取一層,然後把整個專案的公共方法以及常量都放進去,然後各個業務的基類都繼承自這個公共的基類。這樣就更合理一點。模型如下圖:

    今天,在回顧Java知識的時候,我又發現了列舉,以及靜態程式碼塊。結合列舉和靜態程式碼塊的使用場景,覺得基類中的一些常量和方法如果放成靜態程式碼塊或者列舉值的話,將更合適。

溫故而知新呀。

    我查了一下JDK的發展歷史,其實在JDK1.5以前,在java程式設計過程中,我們通常需要定義一些固定數量的常量,通常的做法是定義一個靜態常量類;但自JDK1.5之後,java引入了列舉(關鍵字enum,全稱為 enumeration,值型別),在列舉中,我們可以把有相關性的常量分組到一個列舉型別裡,列舉也比常量類有更多靈活的用法,使用列舉,可以有效的提高程式碼的整潔性、可讀性、可維護性等等,這裡簡單總結一下常用的列舉用法。

下面看一下列舉的使用場景:

1、作為普通的常量使用,如星期、季節、顏色、城市等等;通常配合switch語句使用。

//定義
//週一到周天列舉
public enum WeekEnum {
    MON,TUES,WED,THURS,FRI,SAT,SUN;
}
//使用
//jdk1.7開始switch語句開始支援String型別,而jdk1.6之前只支援int,char,enum型別,使用列舉的話,能使程式碼的可讀性大大增強
public class TestEnum {
    public static void main(String[] args) {
        WeekEnum week 
= WeekEnum.TUES; switch (week) { case MON: System.out.println("星期一"); break; case TUES: System.out.println("星期二"); break; case WED: System.out.println("星期三"); break; case THURS: System.out.println("星期四"); break; case FRI: System.out.println("星期五"); break; case SAT: System.out.println("星期六"); break; case SUN: System.out.println("星期天"); break; } } }

 

2、往列舉中新增變數、建構函式、以達到靈活獲取指定值的目的(注: Java 要求必須先定義 enum 例項,否則編譯會報錯);通常用於一些業務系統中定義一些固定值,如用於匹配db中的欄位值等。我發現我最近程式碼中的一些常量可以使用這種方法來替換。

//定義
//利用建構函式將變數賦值,然後通過get方法獲取指定值
 public enum CompanyEnum {
    SF("順豐速運", 1001), YTO("圓通速遞", 1002),STO("申通物流",1003),YD("韻達快運",1004),YZPY("中國郵政",1005);
    private CompanyEnum(String company, int code) {
        this.company = company;
        this.code = code;
    }
    private String company; // 公司名稱
    private int code; // 公司編碼
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}
//使用
//輸出->1001 、 順豐速運
public class TestEnum {
    public static void main(String[] args) {
        System.out.println(CompanyEnum.SF.getCode());
        System.out.println(CompanyEnum.SF.getCompany());
    }
}

 

3、往列舉中新增自己特定方法,以實現自己所需的相關業務邏輯。

//定義
public enum CompanyEnum {
    SF("順豐速運", 1001), YTO("圓通速遞", 1002), STO("申通物流", 1003), YD("韻達快運", 1004), YZPY("中國郵政", 1005);
    private CompanyEnum(String company, int code) {
        this.company = company;
        this.code = code;
    }
    private String company; // 公司名稱
    private int code; // 公司編碼
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    //根據物流公司名字獲取對應的編碼
    public static int getCodeByCompany(String company) {
        for (CompanyEnum c : CompanyEnum.values()) {
            if (c.getCompany().equals(company.trim())) {
                return c.code;
            }
        }
        return 0;
    }
    //根據物流公司編碼獲取對應的名字
    public static String getCompanyByCode(int code) {
        for (CompanyEnum c : CompanyEnum.values()) {
            if (c.getCode() == code) {
                return c.getCompany();
            }
        }
        return null;
    }
}

//使用
//輸出->1001 、 圓通速遞 
public class TestEnum {
    public static void main(String[] args) {
        System.out.println(CompanyEnum.getCodeByCompany("順豐速運"));
        System.out.println(CompanyEnum.getCompanyByCode(1002));
    }
}

 

這種列舉用法,通常還可用於系統的錯誤碼與對應的錯誤碼描述,然後根據錯誤碼獲取錯誤碼對應的描述。

4. 其它用法,java中的列舉還有許多其它的用法,如重寫toString()、equals()等方法,實現介面、列舉Map等等,直接給2個簡單的例子吧。

/**
* 列舉本身的一些方法使用
*/
public class TestEnum {
    public static void main(String[] args) {
        //返回此列舉常量的名稱,繼承自java.lang.Enum類,通常重寫該方法以實現相關操作。輸出->SF
        System.out.println(CompanyEnum.SF.toString());
        //返回此列舉常量的名稱。輸出->SF
        System.out.println(CompanyEnum.SF.name());
        //返回列舉常量的序數(它在列舉宣告中的位置,其中初始常量序數為零)。輸出->0
        System.out.println(CompanyEnum.SF.ordinal());
        //獲取列舉中的常量個數。輸出->5
        System.out.println(CompanyEnum.SF.values().length);
        //返回帶指定名稱的指定列舉型別的列舉常量。輸出->順豐速運
        System.out.println(CompanyEnum.SF.valueOf(CompanyEnum.class, "SF").getCompany());  
        //比較此列舉與指定物件的順序;SF位置是0,YTO位置是1,結果為 0-1=-1。輸出->-1
        System.out.println(CompanyEnum.SF.compareTo(CompanyEnum.YTO)); 
        //返回與此列舉常量的列舉型別相對應的 Class 物件。輸出->class com.cndmss.util.CompanyEnum
        System.out.println(CompanyEnum.SF.getDeclaringClass());
        //。輸出->true
        System.out.println(CompanyEnum.SF.name().equals("SF"));
        //。輸出->true
        System.out.println(CompanyEnum.SF.equals(CompanyEnum.SF));
        //。輸出->false
        System.out.println(CompanyEnum.SF.equals(CompanyEnum.YTO));
    }
}
/**
 *EnumSet、EnumMap的使用
 */
public class TestEnum {
    public static void main(String[] args) {
         //1、 EnumSet的使用
        EnumSet<CompanyEnum> companySet = EnumSet.allOf(CompanyEnum.class);
        for (CompanyEnum company:companySet) {
            System.out.println(company.getCode() + ":" + company.getCompany());
        }
        //2、EnumMap的使用
        EnumMap<CompanyEnum, String> companyMap = new EnumMap(CompanyEnum.class);
        companyMap.put(CompanyEnum.SF, "順豐map");
        companyMap.put(CompanyEnum.YTO, "圓通map");
        Iterator<Entry<CompanyEnum, String>> iter = companyMap.entrySet().iterator();
        while(iter.hasNext()){
            Entry<CompanyEnum, String> entry = iter.next();
            System.out.println(entry.getKey().name() + ":" + entry.getValue());
        }
    }
}

 

Java中,所有列舉類都是繼承java.lang.Enum類,可以把 enum 看成是一個普通的 class,它們都可以定義一些屬性和方法,因為java是單繼承,所以列舉不能再繼承其它類,但列舉可以實現介面。

 

好早之前找的資料完了出自哪位前輩的了QAQ