在阅读《阿里巴巴Java开发手册》时,发现有一条关于关于常量定义的规约,具体内容如下:

图中的反例是将数据缓存起来,并使用魔法值加链路 id 组成 key,这就可能会出现其他开发人员在复制粘贴的时候,少复制 _ 的情况发生,这种错误很难去检查到,因为读取缓存不存在,可能会去数据库读取,很难察觉到。

如果在生产环境中,大量的请求进来,缓存全部失效,直接请求数据库,导致数据库连接过多,查询效率变低的问题发生,因此看来魔法值确实应该避免出现在代码中。

另外在 《Clean Code》 和 《重构》 等书中也提到了类似的问题,在代码中出现原始形态数字通常来说是坏现象,应该用命名良好的常量类隐藏它。

静态常量取代魔法值

像下面这个例子:

if (billCount > 75) {
    //todo
} else {
    //todo
}

如果在不了解这块的业务的同事,在读到这块代码的时候,可能会想,75 是什么鬼,为啥和这个数比较,背后深藏着什么秘密吗?可能只有当时的开发人员记得了,导致代码可读性和可维护性极差。

如果声明一个常量,来替换该魔法值,可能就会使代码的可读性和可维护性大大增加。

static final Integer BASIC_BILL_COUNT = 75;

还有些魔法表达式,比如:

if (value > 60 && value <= 80 && type = 1) {
    // todo
}

比如这个表达式是表示状态为正常且项目活跃,就可以定义:

boolean isActiveProject = value > 60 && value <= 80 && type = 1;

这样是不是可读性就提高了,一眼就可以看出来这块代码的逻辑。

枚举类取代魔法值

还有一种消除魔法值的方式是使用枚举类代替,下面让我们举个例子:

if (eventId == 1) {
    System.out.println("睡觉");
} else if (eventId == 2) {
    System.out.println("吃饭");
} else if (eventId == 3) {
    Syst