常量的病态使用

Morbid use of constants

我为什么要写(正如我的同事所说):

import static org.apache.commons.lang.math.NumberUtils.INTEGER_ONE;
if (myIntVariable == INTEGER_ONE) { ... }

而不是:

if (myIntVariable == 1) { ... }

?

我知道建议使用常量,但我认为 NumberUtils.INTEGER_ONE 的值永远不会改变!所以我写 1.

你可能知道它是否永远不会改变,但如果我开始编辑你的代码我就不会...

基本上,这是一种在您的实际代码中记录您的代码的方法。像这样使用常量和示例的原因是为了避免 Magic Numbers in code and their disadvantages.

话虽这么说,但您可以将它用到不再有利和导致混乱的地步。我倾向于对不止一次使用的东西或有被我或其他人改变的概念的东西这样做......或者用更简单的术语来说 重要 值。

org.apache.commons.lang.math.NumberUtils.INTEGER_ONE 它给你一个 final static Integer 对象而不是原始的 int 1,而且 final static 它作为一个常量可以用于比较Integer 个对象,因为总是 return 个相同的实例。

所以在上面的场景中它可能看起来不合适但是如果你在比较的时候使用它,它肯定会产生影响。

此外,我们应该尽可能地更喜欢使用常量而不是硬编码,因为:

  1. 它可以使您的代码易于维护。如果以后有什么情况需要改,只能在一个地方改。
  2. 代码看起来更清晰、更易读。

你不应该。 INTEGER_ONE 名称的意义不亚于 1。但是,如果此值具有其他含义(例如,一年中的月份),那么使用常量(如 Calendar.FEBRUARY)将使您的代码更清晰。

我猜想 Commons Math 库中的这个常量是在 Java 1.4 中创建的,当时还没有整数缓存和自动装箱,因此就可以重复使用相同的 Integer 而言是有意义的对象(不是原始 int)在不同的地方以节省内存。所以添加它是出于性能原因,而不是为了代码清晰。现在它已经过时了:即使你需要一个 Integer 对象,你也可以使用 Integer.valueOf(1) 或隐式自动装箱并获取缓存的对象。

假设你有这个

if (myIntVariable == 1) { ... }

但是几千次...

然后突然需要一个 2。

你改什么比较容易?

编辑:在投票之前,我是从不使用幻数的优点的角度回答的,我没有以任何方式(我认为这是可以推断的,拜托人们)建议更改库常量。

你应该INTEGER_ONE!你也不应该写 1 (见下面的例外)!

为什么?像 1 这样的文字被称为 magic number。幻数是 "unique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants"(来自同一维基百科页面的解释)。

所以通常应该做的是将那些神奇的数字变成常量,其名称代表或解释该数字的含义。常量INTEGER_ONE不解释意思

因此,您实际上要做的是找到该值在此上下文中的含义,并创建一个与该名称完全相同的常量。例如,如果 1 表示允许的最大线程数,您应该有一个常量,如:

static final int MAX_NUMBER_OF_THREADS = 1;

根据 Tagir 的评论进行编辑

如果文字本身在您为其编写代码的域中具有意义,则不应将其替换为命名常量。 Tagir计算逆元的例子很好:

double invert(double x) {
    return 1/x;
}

这里的文字 1 在数学领域内的上下文中具有意义。所以它可以按原样使用。

Class NumberUtils 你会看到它被定义为:

/** Reusable Integer constant for one. */
public static final Integer INTEGER_ONE = new Integer(1)

因此,您会看到 INTEGER_ONE 与 1 不同。它是一个已经为您构建的对象。因此,如果我们需要 Integer(1) 的实例,而不是创建您自己的实例,您可以重复使用库中的实例,从而节省时间和内存。

这真的取决于你的应用程序,如果你确实是 1 的 int 版本,那么,你最好使用那个而不是这个 Integer class .

我刚刚为我的公司编写了风格指南,我建议如下:

Don't use hard coded, "magic" values. If a value is constant, define it as such. Numbers such as -1, 0, 1, 2, 100 can be used in some situations.

我的示例使用 Objective-C,因为这是我编写指南所用的语言,但规则仍然适用。

很好用

static NSString* const DatabaseName = @"database.name";

//Acceptable use of "2"
float x = (ScreenWidth / 2) - (ImageWidth / 2);

//Acceptable use of 0
for (int i = 0; i < NumberOfItems; i++)

//Acceptable use of 100, but only because the variable is called "percentage"
float percentage = (someObjects * 100) / allObjects.count;

错误用法

float x = (480 / 2) - (120 / 2); //We have to guess these are sizes?

//Unneccessary constants.
for (int i = ZERO; i < NumberOfItems; i += ONE)

float percentage = (someObjects.count * 100) / 120; //What is 120?