枚举 vs 静态常量,内存占用

18

首先看一下 Android 开发者指南中的以下引用:

尽管第一个要点中给出了“严格避免在 Android 上使用枚举类型”的不详警告,但是该要点下面所说的实际上并不像听起来那么糟糕。常量是32位整数,而枚举类型可能是64位引用。有关枚举类型成本加倍的数学计算是有道理的,似乎并不那么可怕。

我的担忧在于,这个警告可能在一定程度上基于第二个要点。

我想知道一个简单的“class”枚举声明是否会带来500字节的开销?每个枚举类型呢?

由于枚举类型可以使用自己的方法而不仅仅是实例,因此它们似乎可以是“扩展类”。简单地说,如果我的枚举类型是 Color,并且我有20种 Color 枚举类型(例如:红色、蓝色、绿色...),那么每个类型就需要500字节的开销吗?


1
除非您创建数千个枚举类,否则它不应该产生明显的差异。 - injecteer
@injecteer 这并不是真的。最终,小事情会累积成为巨大的差异,请观看这个关于Android开发者的优秀教程:https://www.youtube.com/watch?v=Hzs6OBcvNQE&index=4&list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu - MBH
2个回答

18

在Android世界中,枚举类型是一个不断进行的无限辩论。

你可以从Romain Guy和Chet Haase在这里的演讲中了解更多关于它的信息:http://www.parleys.com/play/5298f999e4b039ad2298c9e3/chapter57/about

根据这段视频,Dalvik中一个对象的大小可以计算为:

overhead of Object + overhead of dlmalloc + data + align
  • 一个对象的开销正好是8个字节。
  • dlmalloc的开销可以是4-8个字节(大多数情况下是8个字节)。
  • 数据的大小取决于数据本身(当然)。
  • 最后,一切都必须是8字节对齐的(例如,如果你有12字节用于一个对象,它将占用16字节)。

请记住,枚举类型的每个值实际上都是枚举类的实例。

另一个需要注意的重要点是dex文件的大小。 例如,以下枚举类型将占用约1,112字节。

public static enum Things {
    THING_1,
    THING_2;
};

或者您可以有两个静态 int,它们将占用 128 字节。

public static int THING_1 = 1;
public static int THING_2 = 2;

您的dex文件大小可以改善10倍。

在编译的dalvik代码生成方面也有很大的不同。对于枚举,编译器会为您做很多事情。在运行时加载类时有一个静态类初始化,这会随着时间而增加启动时间。

另一方面,枚举也带来了许多优点:可读性、可用性和类型安全等。我只会在特殊的极端情况下担心枚举。

特别是当我们考虑使用ProGuard时,它可以将枚举优化为普通的int常量。


请解释1,112字节和128的数字是从哪里来的。然后它们不适合任何东西。 - Damian Leszczyński - Vash
+1 不错的链接。1112 vs. 128 是从反编译字节码中得出的。但他们没有分解任何关于类与每种类型成本的度量。 - NameSpace
@NameSpace,这是dex文件的大小。它在运行时内存中没有太多共同点,但在.apk大小上有所不同。 - Damian Leszczyński - Vash
dex文件的大小确实会影响运行时内存使用,因为它在运行时加载到内存中。 - Eliezer

2
您误读了这条信息。
您引用的是:
“Java中每个类(包括匿名内部类)使用约500字节的代码。”
这意味着需要将类定义存储在某个位置并占用500字节。
这意味着enum Const {}class Const {}没有区别。
更重要的是,当创建实例时对象占用多少内存。
每个类实例有12-16字节的RAM开销。--来自源代码的下一行。
总结一下,只有当它们在同一个长容器(枚举或类)中声明时,您才能从int值的常量中受益。
实际上,枚举也是扩展Enum<?>类型的类,并且它的实例比静态int常量需要更多的内存。
在这里进行交易的是内存消耗和类型安全代码。当您将int用作常量时,无法确保类型安全。
现代设备上可以编写消耗更多内存的代码。但对于您的代码的某些方面,可能更容易使用int,而其他枚举则是正确的选择。这在androind R包上特别明显,其中代码量非常大。
在这种情况下,应该对小域字段使用int,而对于枚举来说则更加安全。

类型安全现在可以通过@IntDef实现,https://developer.android.com/reference/android/support/annotation/IntDef.html - Kenneth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接