Java 最佳实践(如避免使用幻数)应该走多远?

Java 最佳实践(如避免使用幻数)应该走多远?,java,coding-style,Java,Coding Style,在不久的将来,我们可能会被一条规则强制执行,根据这条规则,我们的java源代码中不能有任何硬编码的数字。所有硬编码的数字必须声明为final变量 尽管这在理论上听起来很棒,但在代码中实现却非常困难/乏味,尤其是遗留代码。将以下代码段中的数字声明为final变量是否真的应该被视为“最佳实践” //creating excel cellnum = 0; //Declaring variables. Object[] result = new Object[2]; //adding dash t

在不久的将来,我们可能会被一条规则强制执行,根据这条规则,我们的java源代码中不能有任何硬编码的数字。所有硬编码的数字必须声明为
final
变量

尽管这在理论上听起来很棒,但在代码中实现却非常困难/乏味,尤其是遗留代码。将以下代码段中的数字声明为
final
变量是否真的应该被视为“最佳实践”

//creating excel
cellnum = 0;

//Declaring variables. 
Object[] result = new Object[2];

//adding dash to ssn
return ssn.substring(1, 3)+"-"+ssn.substring(3, 5)+"-"+ssn.substring(5, 9);
以上只是我能想到的一些例子,但在这些(和其他)例子中,作为一名开发人员,您会在哪里说“够了就够了”


我想让这个问题成为一个社区维基,但看不出如何…?

肯定。文字常量有其位置,尤其是低常量,如
0
1
2

我想没有人会这么想

double[] pair = new double[PAIR_COUNT];

double[] pair = new double[2];
我会说,如果需要,使用最终变量

  • …它增加了可读性
  • …该值可能会更改(并在多个位置使用),或
  • …它用作文档


一个相关的旁注:与编码标准/约定一样:应该严格遵守很少(如果有的话)的规则。

一般来说,如果一个文字有特殊的含义,应该给它一个唯一的名称,而不是假设的东西。我不知道为什么这样做“实际上”很难/乏味

Object[]result=新对象[2]=>似乎是使用Pair类的一个很好的候选者

cellnum=0=>cellnum=第一列;esp,因为您可能最终使用的API将1作为起始索引,或者您可能希望处理列从2开始的excel


返回ssn.substring(1,3)+“-”+ssn.substring(3,5)+“-”+ssn.substring(5,9)
=>如果您的代码库中到处都是这样的代码,您会遇到更大的问题。如果这个代码存在于一个单一的位置,并被一个理智的API屏蔽,我在这里并没有真正看到一个问题。

< P>我看到人们认为0和1个例外。p> 其思想是,您希望记录为什么有两个对象,例如上面提到的对象。 关于SSN中的破折号,我同意你的看法。注释对它的描述优于4个命名常量


总的来说,我喜欢没有神奇数字的想法,但就像每一条规则一样,都涉及到语用学。遗留代码带来了它自己的问题。以这种方式更新旧代码需要大量的工作,但在改变行为方面却没有很大的生产力。我会考虑以一种渐进的方式来做:当你必须编辑一个旧文件时,把它更新。

取决于它是否需要改变。或者就这一点而言,它可以改变


如果你只需要2个对象(比如,对于像aioobe这样的一对对象),那么这不是一个神奇的数字,而是一个正确的数字。如果是一个变量元组,此时为2,那么您可能应该将其抽象为一个常量。

这实际上取决于上下文,不是吗。如果代码中有数字没有指明它们存在的原因,那么命名它们会使代码更具可读性。如果你看到代码中的数字3.14是PI吗?有没有办法告诉你,或者这只是巧合?将其命名为PI将解开谜团


在您的示例中,为什么cellnum=2?为什么不是10?还是20?它应该被命名为某个东西,比如说初始单元或最大单元。特别是如果相同的数字,意味着相同的东西再次出现在代码中。

如果仅从数值上看,数字本身的意义并不明显,那么用常量替换数字是有意义的

比如说,

productType = 221; // BAD: the number needs to be looked up somewhere to understand its meaning
productType = PRODUCT_TYPE_CONSUMABLE; // GOOD: the constant is self-describing
另一方面,

int initialCount = 0; // GOOD: in this context zero really means zero
int initialCount = ZERO; // BAD: the number value is clear, and there's no need to add a self-referencing constant name if there's no other meaning

好。我的意见是一样的。它需要控制,而不是将每个数字标记为硬编码的数字,并检查长度为0的字符串等。右:-)
if(index<0 | | index>arr.length)throw…
vs
if(indexarr.length)例如,抛出…
final
除了让你看代码之外,还有什么作用呢?如果在那里进行任何解析都需要可插入的正则表达式才能使其具有多功能。相信者相信,当需要更改某个值时,将一个变量设为final并在其他地方重用它将是有益的,但是,当声明数组或子字符串的ssn总是9位时,这种理论没有意义。问题仅限于ssn示例。您的
ssn
语句索引被关闭1。