何时使用枚举/整数常量

16

我有一个问题:什么时候应该使用枚举,什么时候应该使用常量?

我知道这个问题已经在Enums and Constants. Which to use when?讨论过了,不过那是关于C#的问题。

我的问题是,为什么Android使用那么多常量而不是枚举?例如, Context

我认为,如果我们使用常量,可能存在以下风险: 如果我们定义一个LEVEL常量,

 public static final int LEVEL_LOW=1;
 public static final int LEVEL_MEDIUM=2;
 public static final int LEVEL_HIGH=3;

当我们传递一个整数参数值为4时,代码不会出现编译错误。但如果我们传递数字1时,代码阅读者可能无法轻松地知道其含义。

但是Enum可以解决这个问题,尽管它可能会导致更多的开销,因为它是对象。

那么为什么Android使用常量而不是枚举?在这种情况下应该何时使用常量或枚举有什么原则吗?


1
当你想确保传递的是预定义常量子集时,可以使用枚举。 - TheLostMind
1
我自己也曾经想过这个问题。我认为Android源代码根本没有使用枚举。 - wvdz
2
在你的代码中使用枚举。在Android中,许多值都是可以添加(OR'ed)的标志。此外,Android核心是“相当古老”的,因此可能是在枚举不是Java的一部分时开始开发的。除此之外,它是一个嵌入式系统,枚举需要更多的内存。 - brummfondel
1
@jaskey 维基百科称Android始于2003年,Java 5于2005年推出。除此之外,核心是使用数字的C/C++。 - brummfondel
3
在我看来,当你在使用一些低级API时,或者资源有限且需要争取每一个可用的KB时,最好使用整数。否则,我认为最好使用枚举类型,因为它们可以防止方法接受无效数据,并提高代码可读性。 - user902383
显示剩余3条评论
5个回答

16

这与安卓历史有关。在Froyo之前的版本中存在未经证实的性能问题,开发人员建议不要使用枚举。自从Froyo以来,“Designing for Performance”文档已被重写,如此处所述。

你可能已经注意到了,我们为Froyo重新编写了“设计性能”的文档。以前它只是一些在某些时候可能是正确的东西,但早已与现实毫无关系。在Froyo中,文档中的每一个声明都由基准测试来证明(或者在未来证明其错误)。 您可以在浏览器中查看“Designing For Performance”基准测试。

但改变遗留内容的结构没有意义。

性能可能与需要存储字符串有关。每个常量创建一个单独类与多个枚举之间存在显着差异。

例如,在Java 7中,如果您有一个具有两个字段的枚举,则需要44个项来轮询常量,而对于具有两个静态最终整数的类,仅需要17个项。

有何区别?

class ContantField {
  public static final int f1 = 0;
  public static final int f2 = 1;
}

enum ContantEnum {
  E1,E2
}
这两个声明在存储和使用方式上非常不同。简化后的 ContantEnum 可以看起来像是:
class ContantEnum {
   public static final Enum enum0    = new Enum("V1",0);
   public static final Enum enum1    = new Enum("V2",1);
   public static final Enum[] values = new Enum[] {enum0,enum1};
} 

通过这种简化,您可以注意到enum需要比int更多的内存资源。

为了回答您的问题,必须理解枚举的作用。枚举的一个作用是增加编译时类型安全性。

为了指出这一点,请看以下示例:

public void setImportantThing(int priviledge, int rights)

public void setImportantThing(Privilege p, Right r)

对于int,我们可以传递任何是int类型的值。而对于enum,我们必须使用正确的枚举值。

这里需要权衡的是编译时验证和运行时内存使用之间的折衷。在决定何时应该使用enum以及何时static int已经足够安全时,你需要自行决策。

注意:enum是Java 1.5版本中引入的,若在此之前使用它们会遇到一些问题more

在Android Studio Beta中,开发者可以使用注解来强制实现类型安全。


6

枚举类型有以下优点:

  • 更安全 - 更具弹性。

    如果修改错误,对枚举列表所做的更改更可能在编译时引起错误。

  • 更清晰 - 大多数开发人员会立即理解这些项目以某种方式相互关联。

    enum { A, B, C } 显然比 psfi A = 0; psfi B = 1; psfi C = 2; 更像是一个有联系的项目组

因此,除非您使用 public static final int 具有可衡量的优势,无论是在内存占用还是速度方面,您都应该始终使用 enum

请参见 何时进行过度优化?


1
基本上,Android核心是C/C++代码。它使用整数。因此,在Java中使用枚举时,每个值都必须进行“翻译”。这将消耗CPU时间和内存。在嵌入式系统上,这两者都很稀缺。

2
Java被翻译成字节码。然后字节码被翻译成Dalvik字节码。Dalvik字节码通过Dalvik VM执行。枚举可以表示为整数。使用字符串的枚举存在开销。这很可能是原因。使用枚举需要存储它们的名称,而不仅仅是整数。 - Damian Leszczyński - Vash
1
但是您必须为每个需要内存的枚举存储整数值。Java不像C那样为枚举提供数字值。 - brummfondel
谢谢!那真的很合理! - JaskeyLam
@brummfondel。这里不是关于int的问题。当你在C或Java中声明枚举时,需要为数字值存储一些字节。Java为枚举提供了数值。构造函数需要一个字符串和整数。差异并非来自int,而是来自那个字符串。枚举创建需要更多的内存。因此,问题不在于需要翻译,而是使用了更多的内存。 - Damian Leszczyński - Vash
正如我所写的,需要更多的内存。那么你在这里遇到了什么问题?除此之外,如果您指定一个成员,Java可以提供数字值,否则没有数字或任何“随机”哈希ID。 - brummfondel

1

0

当我个人编程时,如果我想要一个名称代表一个重要的整数,我会使用您上面提到的方法。例如,MAX_INT 可以映射到 int 50。这很有用,因为我可以将 int 更改为 60,而无需浏览所有代码并将我的 50 更改为 60。

使用枚举类型(正如this link所解释的那样),它是一种特殊的数据类型,使变量成为预定义常量集合。因此,如果您想要从受限制的值集中进行选择,则这将是一个理想的选择 - 而您选择的上述样式将是可扩展的,并且易于通过选择不在范围内的值来利用。


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