编码规范 - 枚举命名

330

在Java中,是否有一种命名枚举的约定惯例?

我的偏好是将枚举视为一种类型。因此,例如,你有一个枚举

Fruit{Apple,Orange,Banana,Pear, ... }

NetworkConnectionType{LAN,Data_3g,Data_4g, ... }

我反对将其命名为:

FruitEnum
NetworkConnectionTypeEnum

我知道很容易挑选出哪些文件是枚举类型,但那样你也会有:

NetworkConnectionClass
FruitClass

此外,是否有一个好的文档描述常量,它们在哪里声明等等?

7个回答

545

枚举是类,应该遵循类的惯例。枚举实例是常量,应该遵循常量的惯例。所以

enum Fruit {APPLE, ORANGE, BANANA, PEAR};

没有必要写FruitEnum,就像没有必要写FruitClass一样。这只是浪费了四个(或五个)没有添加任何信息的字符。

这种方法被Java™教程的示例所推荐和使用。


28
我曾经以那种方式命名我的枚举,但为了可读性,现在我使用Fruit.Apple而不是Fruit.APPLE。 - Walter White
45
为什么让枚举实例看起来像类会增强可读性? - DJClayworth
22
从技术上讲,枚举实例确实是类。这就是它们能够拥有方法的原因。 - Ted Hopp
100
不,枚举实例是一个实例。枚举是一个类。 - DJClayworth
33
一个让我需要输入 Fruit.APPLE.chew() 的命名模式的想法让我很不爽。另外,虽然这是一种非常糟糕的做法,但 APPLE 不一定要是一个常量(不可变)。随着枚举被晋升为 Java 类的全功能,我不确定是否总是有意义使用为 c 中不存在的东西(对象,而不是枚举)开发的约定。 - Bill K
显示剩余16条评论

83
这可能不会让我结交很多新朋友,但应该补充一下:C#的开发者有不同的指导方针:枚举实例采用“帕斯卡命名法”(大小写混合)。请参见stackoverflow讨论MSDN枚举类型命名指南
由于我们正在与C#系统交换数据,我倾向于完全复制他们的枚举,忽略Java的“常量名称为大写字母”的约定。想一想,我并没有看到在枚举实例中被限制为大写字母的价值。对于某些目的来说,.name()是一个方便的快捷方式,可以得到枚举常量的可读表示,并且混合大小写的名称看起来更好。
所以,是的,我敢质疑Java枚举命名约定的价值。事实上,“编程世界的另一半”确实使用了不同的风格,这使我认为怀疑自己的信仰是合理的。

10
今天我学到,只有Java或C#程序员才是真正的程序员,并且他们的数量相等。 #讽刺 - Mindwin Remember Monica
25
C# 是一门非常好的编程语言,但其中有一点实在是太荒谬了。在 C# 中,几乎所有的东西都是帕斯卡命名法,这基本上等同于没有任何命名规范;从名称上你看不出它是类、方法、属性等等。 - Bassinator
4
布尔类型实际上是一种枚举类型,它只有两个实例,分别为true和false,需使用小写字母。因此,全大写的写法是不美观的。 - Florian F
@FlorianF,请不要混淆基本类型boolean和类Boolean(https://docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html)。该类使用大写约定。 - IvoC

33

如已经声明的,根据Oracle网站上的文档(http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html),枚举实例应该大写。

然而,在查看Oracle网站上的JavaEE7教程(http://www.oracle.com/technetwork/java/javaee/downloads/index.html)时,我偶然发现了“Duke's bookstore”教程中一个类(tutorial\examples\case-studies\dukes-bookstore\src\main\java\javaeetutorial\dukesbookstore\components\AreaComponent.java)中的以下枚举定义:

private enum PropertyKeys {
    alt, coords, shape, targetImage;
}

按照惯例,它应该看起来像:

public enum PropertyKeys {
    ALT("alt"), COORDS("coords"), SHAPE("shape"), TARGET_IMAGE("targetImage");

    private final String val;

    private PropertyKeys(String val) {
        this.val = val;
    }

    @Override
    public String toString() {
        return val;
    }
}

看起来甚至 Oracle 的员工有时也会在传统和方便之间进行权衡。


5
这里枚举的名称也不正确。它必须是 PropertyKey 而不是 PropertyKeys,因为使用此类型的变量只表示一个键。 - Markus Hettich

17

在我们的代码库中,通常会在它们所属的类中声明枚举。

以你提到的Fruit(水果)为例,我们会有一个Fruit类,在里面有一个名为Fruits的枚举。

在代码中引用它的方式如下:Fruit.Fruits.AppleFruit.Fruits.Pear等等。

常量也遵循同样的方式,它们要么被定义在它们相关的类中(比如Fruit.ORANGE_BUSHEL_SIZE);或者如果它们适用于整个系统(例如int类型的等效“空值”),则放在名为“ConstantManager”(或类似名称)的类中(例如ConstantManager.NULL_INT)。 (顺便说一下,我们所有的常量都是大写字母)

像往常一样,你的编码标准可能与我的不同,所以可能会有所不同。


5
我想补充一点,现在似乎物体工厂的命名通常使用复数,例如 ListsMaps。我认为这是一个好的约定,并且完全支持它更广泛的使用。 - Esko
是的,它们与我的个人编码标准相似,但不同于我的工作场所的编码标准。我们在工作中没有很多规范,所以我正在尝试找到一个好的文档用作参考。 - Walter White
9
“Fruit.Fruits.Apple” 对我来说过于啰嗦了,实际上违反了DRY原则 :-) 我更喜欢例如“Fruit.Type.APPLE”的写法。 - Péter Török
2
我不喜欢这种方法。这个命名方式,一个苹果要么是水果,要么至少令人困惑,因为不清楚苹果不是水果。我喜欢彼得的类型示例。至少这样就可以自我记录APPLE是一种水果。虽然整个水果示例看起来有点腐烂... - Mark Peters
1
我也不喜欢这个。如果“Fruit”类表示水果(它应该是这样的),那么“Fruits”可以代表什么呢?如果Fruit(该类)确实是用于处理水果的类,那么它应该重命名为“FruitHandler”或“FruitManager”。 - DJClayworth
我同意Mark和DJ的观点:在你的例子中看起来很好,但是Fruits fruits = Fruits.APPLE;显然不行。 - Maarten Bodewes

7
他们仍然是类型,因此我始终使用与类相同的命名约定。
我绝对不会在名称中加入“Class”或“Enum”。如果你同时拥有一个和一个,那么肯定有其他问题,你需要更具描述性的名称。我正在思考会导致需要两者的代码类型,并且似乎应该有一个基于<水果>的基类而不是枚举类型。(这只是我的猜测,你可能有不同于我想象的情况。)
关于常量命名,我能找到的最好参考资料来自变量教程:
如果您选择的名称只由一个单词组成,请将该单词拼写为全小写字母。如果它由多个单词组成,请大写每个后续单词的第一个字母。变量名gearRatio和currentGear是这种约定的典型示例。如果您的变量存储常量值(例如static final int NUM_GEARS = 6),则约定略有不同,每个字母都要大写,并使用下划线字符分隔后续单词。按照惯例,下划线字符从不在其他地方使用。

常量命名的参考资料在 http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html#15436。 - Christoffer Hammarström

3

如果我可以提供我的意见,我更喜欢在C中将枚举值使用PascalCase。

在C中,它们基本上是全局的,PEER_CONNECTED与PeerConnected相比变得非常繁琐。

清新的空气。

确切地说,它让我呼吸更轻松。

在Java中,只要您从另一个类中静态导入它们,就可以使用原始枚举名称。

import static pkg.EnumClass.*;

现在,您可以使用已经以不同方式合格的非限定名称。
我目前正在考虑将一些C代码移植到Java,并且目前在选择Java约定(更冗长、更丑陋),还是我的C风格之间犹豫不决。
PeerConnected将变成PeerState.CONNECTED,除了在switch语句中,它是CONNECTED。
现在有很多值得称赞的惯用语,看起来很好,但某些“惯用短语”例如if (s == PeerAvailable) 就会变成if (s == PeerState.AVAILABLE),而对我来说,这是意义的损失。
我认为我仍然喜欢Java风格,因为它更清晰,但我很难看着这种喊出来的代码。
现在我意识到PascalCase已经被广泛应用于Java中,但它并不真正困扰,只是有点不协调。

0
enum MyEnum {VALUE_1,VALUE_2}

这(大约)等于是在说

class MyEnum {

    public static final MyEnum VALUE_1 = new MyEnum("VALUE_1");
    public static final MyEnum VALUE_2 = new MyEnum("VALUE_2");

    private final name;

    private MyEnum(String name) {
        this.name = name;
    }

    public String name() { return this.name }
}

所以我猜全大写字母严格来说更正确,但我仍然使用类名约定,因为我讨厌任何地方都用全大写字母


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