Android 開發中是否應該使用枚舉?


本文由咕咚發布在個人博客,轉載請注明出處。

本文永久地址:https://gudong.name/2019/11/04/use-enum-or-not.html


在 Android 官方文檔推出性能優化的時候,從一開始有這樣一段說明:

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.

意思是說在 Android 平台上 avoid 使用枚舉,因為枚舉類比一般的靜態常量多占用兩倍的空間。

如果你還不了解枚舉,參看文章 枚舉介紹以及枚舉的本質

由於枚舉最終的實現原理還是類,在編譯完成后,最終為每一種類型生成一個靜態對象,而在內存申請方面,對象需要的內存空間遠大於普通的靜態常量,而且分析枚舉對象的成員變量可知,每一個對象中默認都會有一個字符數組空間的申請,計算下來,枚舉需要的空間遠大於普通的靜態變量。具體分析可見這篇文章

所以,照此來看,在 Android 這樣對內存寸土必爭的平台上,如果只是使用枚舉來標記類型,那使用靜態常量確實更優,但是現在翻看官方文檔發現,這個建議已經被刪除了。(

為什么官方會刪除?難道是之前的建議有錯誤嗎,或者描述的不夠精確?

個人認為,枚舉占用空間比普通類型的靜態常量大,這是事實,沒問題,但是據此就建議不在 Android 中使用時不妥的,具體看 JakeWharton 在 reddit 上的一個評論

The fact that enums are full classes often gets overlooked. They can implement interfaces. They can have methods in the enum class and/or in each constant. And in the cases where you aren't doing that, ProGuard turns them back into ints anyway.

The advice was wrong for application developers then. It's remains wrong now.

最重要的一句是

ProGuard turns them back into ints anyway.

在開啟 ProGuard 優化的情況下,枚舉會被轉為 int 類型,所以內存占用問題是可以忽略的。具體可參看 ProGuard 的優化列表頁面 Optimizations Page,其中就列舉了 enum 被優化的項,如下所示:

class/unboxing/enum

Simplifies enum types to integer constants, whenever possible.

既然 ProGuard 會把枚舉優化為整形,那是不是在 Android 中,就可以繼續無所顧忌的使用枚舉了呢?😊

並不是!!!

ProGuard 對枚舉的優化有一定的限制條件,如果枚舉類存在如下的情況,將不會有優化為整形,如下所示:

  1. 枚舉實現了自定義接口。並且被調用。
  2. 代碼中使用了不同簽名來存儲枚舉。
  3. 使用 instanceof 指令判斷。
  4. 在枚舉加鎖操作。
  5. 對枚舉強轉。
  6. 在代碼中調用靜態方法 valueOf 方法。
  7. 定義可以外部訪問的方法。

參考自:ProGuard 初探 · dim's blog,另外,上面的這七種情況,我並沒有找到官方的說明,如果有哪位讀者知道,請在評論區里留下鏈接,謝謝啦~

也就是說,要保證枚舉能被正常優化為整形,就要確保枚舉足夠簡單,如下所示,這些情況下的枚舉都是可以被優化的

enum Color{
  Red,Black,Green
}

或者這樣的

enum Date {
  Sunday("星期日"), 
  Monday("星期一"), 
  Tuesday("星期二"), 
  Wednesday("星期三"), 
  Thursday("星期四"), 
  Friday("星期五"), 
  Saturday("星期六");

  public String value;

  private Date(String value) {
    this.value = value;
  }
}

但是再次查看那七條規則,會發現這幾個規則幾乎把枚舉面向對象的特性都限制了,在這樣的限制下,枚舉好用的地方都將消失,失去了枚舉的靈活性。

到這里就有點矛盾了,枚舉很好用,ProGuard 也會對它進行優化,但是優化條件限制了我們更好的使用枚舉,那我們應該怎么面對這種情況,我的幾點建議:

  • 對於簡單的使用場景,比如 Color、Week 這種,枚舉有更好的語義性,可以優先使用枚舉。
  • 一些時候使用枚舉可能無法避免上面七種情況的,權衡易用性和性能以及使用場景,可以考慮繼續使用枚舉,因為枚舉在有些時候確實讓代碼更簡潔,更容易維護,犧牲點內存也無妨。

至於 Android 為什么會把那條優化建議刪掉,我認為官方也是考慮到了枚舉會被優化為整形這一點,所以才去掉的。

然后實際工作中具體怎么使用,官方就不在說 ”avoid“ 了,而是讓開發者自行決定是不是使用枚舉。

以上就是關於 [Android 開發中是否應該使用枚舉?] 這個問題我的一些思考。

關於作者

咕咚,Android 工程師,個人博客 gudong.name,公眾號:咕喱咕咚

公眾號:咕喱咕咚

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM