The price of ENUMs
在StackOverFlow等问答社区常常出现关于在Android系统里面使用枚举类型的性能讨论,关于这一点,Android官方的Training课程里面有下面这样一句话:
Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
关于enum的效率,请看下面的讨论。假设我们有这样一份代码,编译之后的dex大小是2556 bytes,在此基础之上,添加一些如下代码,这些代码使用普通static常量相关作为判断值:
增加上面那段代码之后,编译成dex的大小是2680 bytes,相比起之前的2556 bytes只增加124 bytes。假如换做使用enum,情况如下:
使用enum之后的dex大小是4188 bytes,相比起2556增加了1632 bytes,增长量是使用static int的13倍。不仅仅如此,使用enum,运行时还会产生额外的内存占用,如下图所示:
Android官方强烈建议不要在Android程序里面使用到enum。
具体原因是为什么呢?下面我们来对其进行分析分析。
下面定义了4个静态常量:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
如果使用Enum表示如下:
- 1
- 2
- 3
- 1
- 2
- 3
我们对Color类进行反编译,进入项目的bin目录,执行 javap -c Color.class
最终结果如下:
我们对上面的反编译代码进行整理如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
上面的代码是根据上面反编译出来的代码编写的,不是标准的,操作过程基本可以呈现。
可以看到,本来是可以使用几个静态常量代替的Color类做了这么多额外的操作,分配了这么多内存,这也是Enum在Android不被建议使用的原因。
从上面的代码可以看到,它其实对上面的几个静态常量做了封装,然后又重新定义了几个静态封装对象,代价非常的大。