为什么Android使用整数而不是枚举?

15

阅读有关Android的资料时,我发现框架的许多部分都使用 int 常量作为返回值或配置值(例如在 START_REDELIVER_INTENT 中的 这个链接中),而不是使用更好的选项之一,即enum。据我所知,这样做有许多原因可以在网络上找到,像这里

那么这就让我想知道...为什么Google决定使用这么多的int而不是enum呢?


1
我猜这是问题的延伸,但他们是否真的不想担心枚举的类型安全方面,并希望通过使用整数常量使事情更加一致? - zgc7009
3
为了节省内存,他们所做的是操作比特位,而不是浪费8个比特,他们只为每个常量使用一个比特。 - Rod_Algonquin
因为与直接使用int相比,使用enum会有更多的内存开销。 - tyczj
@zgc7009,您介意详细说明一下“担心枚举的类型安全方面”吗? - StoneMan
1
重新打开,因为提出的重复问题实际上是在问一个不同的问题,并且没有满足此处所问问题的答案。 - Chris Stratton
显示剩余7条评论
3个回答

8

1
这不是主要原因。 - Chris Stratton
3
@ChrisStratton的问题是:“为什么Google决定使用这么多int而不是enum?”。Google的文档中写道:“枚举类型通常需要的内存比静态常量多两倍以上。你应该严格避免在Android上使用枚举类型。”请告诉我这如何与问题相关?谷歌的回答并没有直接回答关于为什么要使用int而不是enum的问题,而是提供了有关在Android上使用枚举类型的建议。这个建议是因为枚举类型占用的内存比静态常量多,而在移动设备上内存通常很宝贵。因此,谷歌建议在Android开发中尽可能避免使用枚举类型。这个建议与@ChrisStratton的问题略有关联,但并未直接回答问题。 - Jack
5
为什么某些开发人员使用了某种技术(这似乎是基于个人观点而被认为是 VTC 的原因)是一个问题。他贴出了谷歌说的谷歌做的理由。对我来说,这听起来像是绝对的答案。我们应该相信您对他们为什么这样做的猜测,而不是他们的文档? - Gabe Sechan
5
换句话说,谷歌的开发人员过度追求过早优化。但我们已经知道了这一点,在他们整个API设计的哲学中显而易见。 - Brodo Fraggins
4
你应该严格避免在Android上使用枚举。哇,这真是糟糕透顶的建议。 - Kevin Krumwiede
显示剩余3条评论

6

操作int类型的速度比枚举类型快得多。

自己判断吧。每次创建一个枚举类型,你至少会创建:

1) Class-loader for it. 
2) You keep this object in memory. 
3) Since enum is static anonymous class - it will always hang in your memory (sometimes even after you close the application.) 

关于 Service。在这个类中,标志主要用于比较并将结果返回给上面的类 (ContextWrapper)。但基本上,如果你深入挖掘 Android SDK,你会自己发现几乎所有这些标志都用于二进制移位操作

即使在 Java 中,JDK 也使用二进制移位操作:

/**
 * Max capacity for a HashMap. Must be a power of two >= MINIMUM_CAPACITY.
 */
private static final int MAXIMUM_CAPACITY = 1 << 30;

您可以查看Android SDK中的Window类,了解更多相关信息。
/**
 * Set the container for this window.  If not set, the DecorWindow
 * operates as a top-level window; otherwise, it negotiates with the
 * container to display itself appropriately.
 *
 * @param container The desired containing Window.
 */
public void setContainer(Window container) {
    mContainer = container;
    if (container != null) {
        // Embedded screens never have a title.
        mFeatures |= 1<<FEATURE_NO_TITLE;
        mLocalFeatures |= 1<<FEATURE_NO_TITLE;
        container.mHasChildren = true;
    }
}

/** The default features enabled */
@SuppressWarnings({"PointlessBitwiseExpression"})
protected static final int DEFAULT_FEATURES = (1 << FEATURE_OPTIONS_PANEL) |
        (1 << FEATURE_CONTEXT_MENU);

所以原因至少有两个:

  • 占用更少的内存。

  • 由于位运算,工作速度更快。


3
这种说法异常复杂,其实是想表达“因为二的幂整数常量可以干净地组合在一起”。 - Chris Stratton
@ChrisStratton 从你对位/二进制的理解中构建表达式。这意味着采用十六进制值和位移常量,而不是它们的十进制等价物。例如,从32位值中提取符号位的掩码可以干净地表示为1 << 31或0x80000000,两者都非常易读。该掩码也恰好是无符号十进制值2147483648,但谁能说得清呢?不要让自己在二进制和十进制之间来回转换以跟上步伐。 - Sergey Shustikov
2
内存消耗不是不使用枚举的荒唐理由。与JVM加载的成百上千个其他类相比,它们所使用的内存量微不足道。同样也不会比任何其他类更难销毁。如果操作系统需要内存,它将终止进程。 - Kevin Krumwiede
2
可以在枚举类型上有效地进行位运算组合:http://docs.oracle.com/javase/7/docs/api/java/util/EnumSet.html - Kevin Krumwiede
5
enum 关键字其实是用来定义一个继承 java.lang.Enum 的普通类的语法糖。Enum 与其他静态类一样在永久代中具有相同的持久性。它们比整型常量使用更多的内存吗?当然是的,但是我们只是讨论几千字节的问题。为了那种微小的优化而牺牲类型安全、目的清晰和可维护性被广泛认为是不好的做法。 - Kevin Krumwiede
显示剩余5条评论

0

正如其他答案所正确指出的那样,原因是枚举类型比 int 使用更多的内存。

为了理解这个决定的背景,您必须记住第一款 Android 设备只有 192MB 的 RAM

正如Google 最接近官方声明的说法所解释的那样,枚举类型不仅是 int 的两倍大,而且当 dex 加载到 RAM 中时,它可能会是 int 的 13 倍。因此,框架团队非常谨慎地在这方面对其代码进行过度优化。如果在 Android 开发时有 4GB RAM 的设备,也许情况会不同,但我们永远不会知道。

非框架开发的建议是根据自己的用例做出判断。请记住,Proguard 通常会将您的枚举类型转换为 int。


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