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

本文由咕咚發佈在我的博客,轉載請註明出處。html

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


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

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

意思是說在 Android 平臺上 avoid 使用枚舉,由於枚舉類比通常的靜態常量多佔用兩倍的空間。數組

若是你還不瞭解枚舉,參看文章 枚舉介紹以及枚舉的本質性能優化

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

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

爲何官方會刪除?難道是以前的建議有錯誤嗎,或者描述的不夠精確?性能

我的認爲,枚舉佔用空間比普通類型的靜態常量大,這是事實,沒問題,可是據此就建議不在 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,公衆號:咕喱咕咚

公衆號:咕喱咕咚

參考連接

相關文章
相關標籤/搜索