列舉是Java 1.5版本增加的特性,列舉是指由一組固定的常量組成的合法值的型別,在還沒有引入列舉的時候,為了表示列舉型別我們常用的方法是宣告一組靜態int 常量。在Effective Java中作者分析了這種模式的許多脆弱之處,因此推薦使用列舉來代替靜態常量方案。
####Effective Java中列舉了使用列舉的的優點:
- 列舉提供了編譯時的型別安全;
- 包含同名常量的多個列舉型別可以在一個系統中和平共處;
- 允許新增任意的方法和域,並實現任意的介面,列舉提供了所有Object方法的高階實現,並實現了Comparable和Serializable介面。
####但是最近在瀏覽Google的官方文件的時候發現,Google是並不不推薦在Android中使用列舉的。 Google的的依據是:
- 列舉通常會比靜態常量多使用超過一倍的記憶體;
- 在每一個類(包括匿名內部類)中多生成500byte的.class的檔案;
- 每一個類的例項有12-16個位元組的RAM開銷;
總結一下: 列舉相對靜態常量最大的有點在於編譯時型別安全,但是記憶體開銷比使用靜態常量大。
####Google為了彌補靜態常量的缺陷,提出了使用IntDef 和StringDef兩個註解來提供編譯時的型別安全 首先引入依賴:
compile 'com.android.support:support-annotations:24.1.1'
複製程式碼
以@IntDef為例的使用方法:
public class MainActivity extends AppCompatActivity {
//宣告靜態常量
public static final int MERCURY = 0;
public static final int VENUS = 1;
public static final int EARTH = 2;
public static final int MARS = 3;
public static final int JUPITER = 4;
public static final int SATURN = 5;
public static final int URANUS = 6;
public static final int NEPTUNE = 7;
//用一個@IntDef({})將其全部變數包含,其次需要一個Retention宣告其保留級別,最後定義其介面名稱
@IntDef({MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE})
@Retention(RetentionPolicy.SOURCE)
public @interface Planet {
}
@Planet
int currentPlanet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@Planet int planet = getCurrentPlanet();
switch (planet) {
case MERCURY:
break;
case VENUS:
break;
case EARTH:
break;
case MARS:
break;
case JUPITER:
break;
case SATURN:
break;
case URANUS:
break;
case NEPTUNE:
break;
default:
break;
}
//傳個8 有錯誤提示
//setCurrentPlanet(8);
}
//只要一個變數使用了@Planet註解,那麼他的值必須屬於Planet
public void setCurrentPlanet(@Planet int currentPlanet) {
this.currentPlanet = currentPlanet;
}
@Planet
private int getCurrentPlanet() {
//如果返回值不屬於Planet,那麼編譯器會提示錯誤 保證了編譯時安全
return currentPlanet;
}
}
複製程式碼