1. 程式人生 > >為什麼推薦使用註解代替列舉?

為什麼推薦使用註解代替列舉?

        在做記憶體優化時, 推薦使用註解代替列舉, 因為列舉佔用的記憶體更高。 這是為什麼呢?

編寫一個最簡單的列舉類, 請問問什麼列舉是靜態的單例? 腦子有點懵~~~

public enum Numbers {
    One,
    Two,
    Three;
}

javac編譯Numbers後生成位元組碼, 我們想看看到底Numbers.class到底有什麼。 因為位元組碼比較晦澀難懂, 還是想辦法用jad反編譯成Java吧,連結: http://www.javadecompilers.com/jad


開啟反編譯生成的Numbers.java

public final class Numbers extends Enum
{

    public static Numbers[] values()
    {
        return (Numbers[])$VALUES.clone();
    }

    public static Numbers valueOf(String name)
    {
        return (Numbers)Enum.valueOf(com/brycegao/test/Numbers, name);
    }

    private Numbers(String s, int i)
    {
        super(s, i);
    }

    public static final Numbers One;
    public static final Numbers Two;
    public static final Numbers Three;
    private static final Numbers $VALUES[];

    static 
    {
        One = new Numbers("One", 0);
        Two = new Numbers("Two", 1);
        Three = new Numbers("Three", 2);
        $VALUES = (new Numbers[] {
            One, Two, Three
        });
    }
}

從上面得到如下結論:

1、列舉類是繼承於java.lang.Enum的類。

2、列舉值是類物件, 且是靜態常量(被static final修飾)。

3、靜態程式碼塊內例項化列舉值,由於靜態程式碼塊的語法特性,該程式碼塊只執行一次;

4、預設值0、1、2是在編譯時生成的。

5、列舉類比常量更佔記憶體, 因為一個Java物件至少佔16個位元組,  而Numbers包含了3個Java物件;而使用3個整型替換的話,只佔用4 * 3即12個位元組。

6、列舉的建構函式是私有的, 防止new出物件。

改用註解實現, Android提供了IntDef和StringDef註解,用於編譯期的型別檢查。 注意: 即使型別不匹配仍然能夠生產apk包, 但IDE會給出提示資訊。

      套路是宣告若干個數值或字串常量後, 建立新的註解(替換列舉)限制取值範圍。

public class Numbers {
    public static final int ONE = 1;
    public static final int TWO = 2;
    public static final int THREE = 3;

    public static final String STR_ONE = "ONE";
    public static final String STR_TWO = "TWO";
    public static final String STR_THREE = "THREE";

    @IntDef({ONE, TWO, THREE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface NumbersInt {

    }

    @StringDef({STR_ONE, STR_TWO, STR_THREE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface NumbersString {

    }
}
        NumbersInt註解限制取值範圍為ONE、TWO、THREE, NumbersString註解限制取值範圍為STR_ONE、STR_TWO、STR_THREE。


       上面程式碼是使用方式, 可以看出value1的引數是合法的, 而values2的引數5屬於非法值,即實現了限制取值範圍的作用, 這種情況並不影響編譯!!!

       註解還可以修飾類成員引數, 限制取值範圍。