1. 為什么要用枚舉矮嫉?
在開發(fā)中我們是不是經(jīng)常都自己定義一些固定不變的靜態(tài)常量來作為其他方法的參數(shù)或者是判斷的條件?比如:
private static final int SEX_GIRL = 0;
private static final int SEX_BOY = 1;
當我們需要把這些作為參數(shù)傳遞的時候贿条,就會出現(xiàn)取值范圍不清楚的問題粹懒,調(diào)用者在不知道源碼的情況下有可能會導致傳值錯誤,比如:
public class Person {
private static final int SEX_GIRL = 0;
private static final int SEX_BOY = 1;
...
private int sex;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
...
Person person = new Person();
person.setSex(23333);
}
噢勺像,天哪障贸,誰知道23333的性別是男的還是女的亦或者是gay?為此吟宦,在Java1.5版本之后篮洁,枚舉就被隆重的請了出來主持大局。
2. 使用enum來避免傳入不合法的參數(shù)
為了避免上面的情況殃姓,下面用枚舉來完善下袁波,代碼如下:
public class Person {
public enum Sex {
SEX_BOY,SEX_GIRL
}
...
private Sex sex;
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
...
Person person = new Person();
person.setSex(Person.Sex.SEX_BOY);
}
這里指定了參數(shù)的類型是Sex,而Sex也只有兩個參數(shù)可選辰狡,避免了上面的傳錯參數(shù)的風險锋叨,比較直觀。
3. 為什么又不用了宛篇?
上面的用法從表面上看起來是沒有什么問題娃磺,的確也是這樣!使用枚舉真的很方便(至少我是這樣認為的)
但是為什么呢叫倍,原因是眾所周知的了偷卧,Android官方文檔中也有說明,enum中的每一個值其實都是一個Object對象吆倦,每聲明一個值就會創(chuàng)建一部分的內(nèi)存以使它能夠被引用到這個對象听诸,相比于靜態(tài)常量,enum會花費近2倍的內(nèi)存空間蚕泽。
到這里可能有人會問晌梨,現(xiàn)在的手機設備基本上都有比較大的內(nèi)存空間桥嗤,再多倍的內(nèi)存創(chuàng)建也能頂?shù)钠鸢桑孔序颍mmu泛领,這個不可否認,現(xiàn)在基本都是大內(nèi)存的設備運行項目也流暢了許多敛惊,但是你不也不能否認的是渊鞋,的確是還存在一部分人的設備還是比較小的內(nèi)存的,開發(fā)不是只為一部分人......而且不要忘記瞧挤,手機為一個應用所創(chuàng)建的內(nèi)存空間還是有限的锡宋。
好吧,扯多了特恬,回到原來思路上执俩。
4. 要怎么做?
剛才也說到鸵鸥,枚舉在很大的程度上是限定了某些屬性值得取值奠滑,當然還有其他別的作用。
既然是限定取值的妒穴,肯定有其他方法的是吧宋税,咱們強大的Google大佬怎么會沒有解決辦法呢!
下面要用到的知識是:@IntDef 讼油、@StringDef杰赛、@Retention、@interface矮台,先上代碼:
public class TestUtil {
public static final int STRING_4G = 0;
public static final int STRING_3G = 1;
public static final int STRING_2G = 2;
public static final int STRING_WIFI = 3;
public static final int STRING_UNKNOWN = 4;
@IntDef({STRING_4G,STRING_3G,STRING_2G,STRING_WIFI,STRING_UNKNOWN})
@Retention(RetentionPolicy.SOURCE)
public @interface NetWorkStatus{}
public static String getNetWorkString(@NetWorkStatus int type) {
if (type == STRING_4G) {
return "NETWORK_4G";
} else if (type == STRING_3G) {
return "NETWORK_3G";
} else if (type == STRING_2G) {
return "NETWORK_2G";
} else if (type == STRING_WIFI) {
return "NETWORK_wifi";
} else {
return "unknown";
}
}
}
其中 @IntDef 定義了需要用到的固定常量乏屯,@Retention 注解告訴編譯器在生成.class文件時不保留枚舉注解數(shù)據(jù)。
而當我們調(diào)用這個方法的時候瘦赫,如果直接傳遞數(shù)值參數(shù)的時候辰晕,lint編譯器就會爆紅色警告,如圖:
5. 其他說明
- 項目中如果存在大量的枚舉使用确虱,不妨試試這種方式代替使用
- 如果用到枚舉操作復雜的邏輯處理含友,按難易程度繼續(xù)適當使用
- 這種方式在直接傳遞數(shù)值時會警告提示,但是不影響實際的運行效果校辩,還是可以傳遞其他數(shù)值進行編譯運行窘问,感覺不太安全,而枚舉可以杜絕這情況的出現(xiàn)
- Android內(nèi)部很多都是差不多這樣操作的宜咒,比如Toast的時間參數(shù)惠赫,如果直接傳遞0則會出現(xiàn)紅色警告,進入源碼會發(fā)現(xiàn)故黑,多了個@的圖標儿咱,如圖:
這跟自己定義的是一樣的庭砍,也有@圖標,如圖: