為什麼推薦使用註解代替列舉?
阿新 • • 發佈:2018-12-25
在做記憶體優化時, 推薦使用註解代替列舉, 因為列舉佔用的記憶體更高。 這是為什麼呢?
編寫一個最簡單的列舉類, 請問問什麼列舉是靜態的單例? 腦子有點懵~~~
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會給出提示資訊。
套路是宣告若干個數值或字串常量後, 建立新的註解(替換列舉)限制取值範圍。
NumbersInt註解限制取值範圍為ONE、TWO、THREE, NumbersString註解限制取值範圍為STR_ONE、STR_TWO、STR_THREE。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 { } }
上面程式碼是使用方式, 可以看出value1的引數是合法的, 而values2的引數5屬於非法值,即實現了限制取值範圍的作用, 這種情況並不影響編譯!!!
註解還可以修飾類成員引數, 限制取值範圍。