一,enum基本用法
-
1,枚舉常量和數(shù)據(jù)有關(guān)聯(lián)
定義:public enum TaskStatus { UN_KNOW(-1, "未知", "#84807f"), UN_START(0, "未開始", "#e2d512"), PROGRESSING(1, "進行中", "#12ea2f"), COMPLETED(2, "已完成", "#c30910"); int mCode; String mDesc; String mColor; TaskStatus(int code , String desc , String color){ mCode = code; mDesc = desc; mColor = color; } public static TaskStatus getTaskStatus(int status) { for (TaskStatus taskStatus : values()) { if (status == taskStatus.mCode) { return taskStatus; } } return UN_START; } }
使用:
TaskStatus taskStatus = TaskStatus.getTaskStatus(status); // status是從服務端獲取的狀態(tài)值 textView.setText(taskStatus.mDesc);
總結(jié):
無論需求如何變化,比如枚舉常量增加一個數(shù)據(jù),或是增加一條狀態(tài),都可以很方便的實現(xiàn),比直接在全局常量類里定義狀態(tài)來的便捷。 -
2,根據(jù)一組狀態(tài)中的某一狀態(tài)執(zhí)行相應的操作
public class Task { public Task(TaskStatus taskStatus) { System.out.println("Season :" + season); } public enum TaskStatus { UN_KNOW, UN_START, PROGRESSING, COMPLETED } public static void main(String[] args) { Task task = new Task(TaskStatus.PROGRESSING); } }
這種方法解決了,直接使用常量類帶來的無法保證類型安全和代碼可讀性差。
二,Android 中使用 enum 的缺陷
在 Android 官網(wǎng)中,已經(jīng)明確指出在 Android 中應嚴格避免使用枚舉,枚舉通常比靜態(tài)常量占用更多的內(nèi)存:Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android
在 Android 官方Android性能優(yōu)化典范系列視頻中有如下比較:
假設(shè)有這樣一份代碼,編譯之后的dex大小是2556 bytes,在此基礎(chǔ)之上,添加一些如下代碼,這些代碼使用普通 static 常量相關(guān)作為判斷值:
假如換做使用
enum
,情況如下: enum
之后的dex大小是4188 bytes,相比起2556增加了1632 bytes,增長量是使用static int
的13倍;此外,每個聲明的enum
和裝載enum
的數(shù)組也要占用內(nèi)存。
因此過度在 Android 開發(fā)中使用 ENUM 將會增大 DEX 大小,并會增大運行時的內(nèi)存分配大小。
不過,在上面的兩種常用方式中,第一種方式所帶來的便捷將大大簡化因需求隨變的工作,相比所帶來的缺點可以忽略;而第二種方式則弊大于利了。
三,解決辦法
1, 為了彌補 Android 平臺不建議使用枚舉的缺陷,官方推出了兩個注解,IntDef和StringDef,用來提供編譯期的類型檢查。
- 添加依賴
在build.gradle文件中的依賴塊中添加:
dependencies { compile 'com.android.support:support-annotations:24.2.0' }
- 聲明常量和
@IntDef
這里@IntDef({ TaskStatus.UN_KNOW, TaskStatus.UN_START, TaskStatus.PROGRESSING, TaskStatus.COMPLETED }) @Retention(RetentionPolicy.SOURCE) public @interface TaskStatus { int UN_KNOW = -1; int UN_START = 0; int PROGRESSING = 1; int COMPLETED = 2; }
TypeDef
注解使用了@interface
來聲明新的枚舉注解類型。其中@IntDef
和@StringDef
注解以及@Retention
標注了新的注解,目的是定義這個枚舉類型。而@Retentino(RententionPolicy.SOURCE)
注解告訴編譯器在生成.class
文件時不保留枚舉注解數(shù)據(jù)。 - 使用
這樣外界就無法傳遞 TaskStatus 之外的成員作為參數(shù)。public static void doSth(@TaskStatus int status){ switch (status){ case TaskStatus.UN_KNOW: //do something break; case TaskStatus.UN_START: break; case TaskStatus.PROGRESSING: break; case TaskStatus.COMPLETED: break; } }
2,如果開啟了Proguard可以在很多情況下將枚舉enum優(yōu)化到整數(shù)對象。
參考:
使用枚舉代替常量,簡化工作!
優(yōu)先使用注解,慎用枚舉
Android 性能:避免在Android上使用ENUM
【內(nèi)存優(yōu)化】避免使用Enum