Java 使用枚举的序号是一种好的做法吗?
我有一个枚举:Java 使用枚举的序号是一种好的做法吗?,java,enums,coding-style,verbose,Java,Enums,Coding Style,Verbose,我有一个枚举: public enum Persons { CHILD, PARENT, GRANDPARENT; } 使用ordinal()方法检查枚举成员之间的“层次结构”是否有问题?我的意思是-当使用它时,排除冗长,当有人可能在将来意外地改变顺序时,有什么缺点吗 还是这样做更好: public enum Persons { CHILD(0), PARENT(1), GRANDPARENT(2); private Intege
public enum Persons {
CHILD,
PARENT,
GRANDPARENT;
}
使用ordinal()
方法检查枚举成员之间的“层次结构”是否有问题?我的意思是-当使用它时,排除冗长,当有人可能在将来意外地改变顺序时,有什么缺点吗
还是这样做更好:
public enum Persons {
CHILD(0),
PARENT(1),
GRANDPARENT(2);
private Integer hierarchy;
private Persons(final Integer hierarchy) {
this.hierarchy = hierarchy;
}
public Integer getHierarchy() {
return hierarchy;
}
}
我将使用您的第二个选项(使用显式整数),这样数值由您而不是由Java分配。第一种方法是不可直接理解的,因为您必须阅读使用枚举的代码才能理解枚举的顺序。
它很容易出错
public enum Persons {
CHILD,
PARENT,
GRANDPARENT;
}
第二种方法更好,因为它是不言自明的:
CHILD(0),
PARENT(1),
GRANDPARENT(2);
private SourceType(final Integer hierarchy) {
this.hierarchy = hierarchy;
}
当然,枚举值的顺序应该与枚举构造函数参数提供的层次顺序一致。
它引入了一种冗余,因为枚举值和枚举构造函数的参数都传达了它们的层次结构。
但为什么会有问题?
枚举用于表示常量且不经常更改的值
OP enum用法很好地说明了良好的enum用法:
CHILD, PARENT, GRANDPARENT
枚举不是为表示频繁移动的值而设计的。在这种情况下,使用枚举可能不是最佳选择,因为它可能会频繁中断使用它的客户端代码,而且每次修改枚举值时都会强制重新编译、重新打包和重新部署应用程序。
使用
ordinal()
不推荐,因为枚举声明中的更改可能会影响序数值
更新:
值得注意的是,枚举字段是常量,可以有重复的值,即
enum Family {
OFFSPRING(0),
PARENT(1),
GRANDPARENT(2),
SIBLING(3),
COUSING(4),
UNCLE(4),
AUNT(4);
private final int hierarchy;
private Family(int hierarchy) {
this.hierarchy = hierarchy;
}
public int getHierarchy() {
return hierarchy;
}
}
这可能是有害的,也可能是有益的,这取决于您计划如何处理层次结构
此外,您可以使用枚举常量来构建自己的enumglags
,而不是使用EnumSet
,例如TLDR:No,您不应该
如果在Enum.java
中为ordinal
方法引用javadoc:
大多数程序员不会使用这种方法。它是
设计用于复杂的基于枚举的数据结构,如
作为java.util.EnumSet
和java.util.EnumMap
首先-阅读手册(本例中为javadoc)
其次,不要编写脆弱的代码。枚举值将来可能会更改,您的第二个代码示例将更加清晰和易于维护
根据java,如果(比如)在父级
和祖辈
之间插入新的枚举值,您肯定不想在将来产生问题
返回此枚举常量的序号(其在
枚举声明,其中初始常量被分配一个
零)。大多数程序员不会使用这种方法。它是
设计用于复杂的基于枚举的数据结构,如
枚举集和枚举映射
您可以通过更改枚举的顺序来控制序号,但不能显式设置。一种解决方法是在枚举中为所需的数字提供一个额外的方法
enum Mobile {
Samsung(400), Nokia(250),Motorola(325);
private final int val;
private Mobile (int v) { val = v; }
public int getVal() { return val; }
}
在这种情况下,
Samsung.ordinal()=0
,但是Samsung.getVal()=400
首先,您可能甚至不需要数字顺序值——这就是
什么
用于,并且Enum
实现可比
如果出于某种原因确实需要一个数字订单值,是的,您应该这样做
使用ordinal()
。这就是它的目的
JavaEnums
的标准实践是按声明顺序排序,
这就是为什么Enum
实现了compariable
以及为什么
Enum.compareTo()
是final
如果您添加自己的非标准比较代码,而该代码不使用
可比性
不依赖于申报顺序,您只需
这会让其他试图使用你的代码的人感到困惑,包括
你自己未来的自我。没有人会期望代码存在;
他们希望Enum
是Enum
如果自定义订单与声明订单不匹配,任何人
看这份声明会感到困惑。如果有
(此时正好)符合申报顺序,有人吗
看着它,人们会想到这一点,他们也会想到这一点
在未来的某个日子里,如果没有,你会受到严重的打击。(如果你写信
编码(或测试)以确保自定义顺序与
声明顺序,您只是在强调它是多么不必要。)
如果您增加了自己的订单价值,那么您就造成了维护方面的麻烦
为你自己:
您需要确保您的层次结构
值是唯一的
如果您在中间添加一个值,则需要重新编号。
后续值
如果您担心有人可能会意外更改订单
以后,编写一个检查顺序的单元测试
总之,用不朽的话来说:
了解并使用图书馆
另外,当您的意思是int
时,不要使用Integer
如果只想在枚举值之间创建关系,实际上可以使用使用其他枚举值的技巧:
请注意,您只能使用在您试图声明的枚举值之前按词汇声明的枚举值,因此只有当您的关系形成一个无环有向图(并且您声明它们的顺序是有效的拓扑排序)时,这才有效。正如Joshua Bloch在《有效Java》中所建议的那样,从序号派生与枚举关联的值不是一个好主意,因为更改枚举值的顺序可能会破坏编码的逻辑
您提到的第二种方法完全遵循作者的建议,即将价值存储在单独的fie中
public enum Person {
GRANDPARENT(null),
PARENT(GRANDPARENT),
CHILD(PARENT);
private final Person parent;
private Person(Person parent) {
this.parent = parent;
}
public final Parent getParent() {
return parent;
}
}
public class Persons {
final public static int CHILD = 0;
final public static int PARENT = 1;
final public static int GRANDPARENT = 2;
}
Persons.CHILD
@Bean
public FilterRegistrationBean compressingFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(compressingFilter());
registration.setName("CompressingFilter");
...
registration.setOrder(1);
return registration;
}
enum FilterRegistrationOrder {
MDC_FILTER,
COMPRESSING_FILTER,
CACHE_CONTROL_FILTER,
SPRING_SECURITY_FILTER,
...
}