2016-11-28 72 views
4

工作的Java 7+警告....假设我们创建一个枚举:生成编译器enum.ordinal

enum Foo{ FOO, BAR } 

然后Foo.FOO.ordinal() == 0。但是,如果我重新排列枚举,请说:

enum Foo{ BAR, FOO } 

then Foo.FOO.ordinal() == 1。这对于大多数人来说是令人惊讶的,因为他们觉得重新排序字段是一个“安全”的操作。毫不奇怪,在大多数情况下,Java推荐使用enum.ordinal()。有很多替代方法,最明显的是(和自我证明)将每个枚举值与一个int相关联。

不幸的是,我公司的一些人没有得到备忘录,我们很多旧代码都使用了遍布整个地方的.ordinal()方法,这取决于int和枚举值之间关联的基本方法。当我有时间时,我会经历并重构,但它不会阻止使用.ordinal()的新代码,这会引入潜在的无法跟踪的错误。

所以!假设我有一个与它关联的很多结构的枚举。我可以以某种方式将.ordinal()标记为不安全,这样如果有人使用(比如说)Foo.FOO.ordinal()会生成编译器警告?

我很满意为此目的使用外部软件包,但如果它们不太模糊,会更喜欢它。

+0

我从来没有这样做,所以把它当作一粒盐;但我会研究像PMD这样的质量工具并编写自定义规则。 – Henry

+0

你的设置是什么?你有一些CI环境吗?例如,我们通过某种Maven插件规则集来阻止从guice中使用@ Inject-Annotation。你想在IDE或git提交钩子或CI系统中发出警告吗? – luk2302

+0

太糟糕了,它是'final',否则你可以覆盖该方法并将其弃用。 – shmosel

回答

1

enum的全部问题是将代码从基础值中分离出来,并且使用ordinal()来破坏目的。

您没有说,但我怀疑问题发生在Java代码和外部存储之间的接口上,即使用ordinal()将枚举“序列化”成可存储在文件或数据库中的东西。

我想你在这里运气不好。作为@Henry说,你唯一的选择可能是一个自定义规则,标志ordinal()所有使用代码分析工具,以及一个巨大的重构工作完成四项任务:

  1. 修改每一个枚举声明不可改变和永久附加一个整数值,独立于ordinal()到每个枚举值。
  2. 对于每个枚举声明,添加一个返回整数值的方法int toInteger()
  3. 对每一个枚举声明中,添加一个方法static EnumClassName fromInteger(int v)为“反序列化”的外在价值
  4. 重构所有引用ordinal()使用新toInteger()fromInteger()方法。
+0

嗯,你已经正确地理解了这个问题。我会暂缓接受一段时间,看看是否有人想出了一个聪明的解决方案,从列表中“执行”(4)。 –

0

这个XPath PMD规则怎么样?

// PrimaryPrefix/Name [ends-with(@Image,'。序“)

只是把它放在一个规则集XML文件中的规则元素是这样的:

<rule name="DontUseEnumOrdinal" message="Please no enums ordinal" 
    class="net.sourceforge.pmd.lang.rule.XPathRule" language="java"> 
    <description>We don't take kindly enum ordinal() round these parts</description> 
    <priority>3</priority> 
    <properties> 
     <property name="xpath"> 
      <value><![CDATA[//PrimaryPrefix/Name[ends-with(@Image, '.ordinal')]]]></value> 
     </property> 
    </properties> 
    <example><![CDATA[MyEnum.MY_VALUE.ordinal(); //is bad 
     MyEnum.MY_VALUE.index(); //is better]]> 
    </example> 
</rule>