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,公众号:咕喱咕咚

公众号:咕喱咕咚

参考连接

相关文章
相关标签/搜索