Java 开发千万别给布尔变量加 is 前缀!很容易背锅

大家好,我是大华。

前几天我在改一个老项目的代码。 本来只是加一个很小的判断,结果一行代码让我卡了 10 分钟。

java 复制代码
if (user.isDeleted()) {
    // ...
}

我心里想:deleted?是已经被删了,还是要不要删除?

于是我顺手点进了 User 类。

java 复制代码
private Boolean isDeleted;

再往下翻方法的时候,我发现有的地方在用:

java 复制代码
user.isDeleted()

有的地方却在用:

java 复制代码
user.getIsDeleted()

这时候问题就来了,到底哪个才是规范写法?

那布尔类型的变量,到底要不要加 is 前缀?


一、入门级的写法

如果你是刚接触 Java 不久,十有八九会这样写:

java 复制代码
private boolean isSuccess;
private boolean isDeleted;
private boolean isEnable;

原因很简单:

  • 布尔值只有 true / false
  • 加个 is,一看就知道是不是

逻辑上完全没问题,而且 IDE、编译器也不会报错。

那问题到底出在哪?


二、场景

我给你还原一个开发中的场景。

1️⃣ 定义阶段:一切都很合理

java 复制代码
private boolean isDeleted;

语义清晰:是否已删除,没毛病。


2️⃣ 生成 getter / setter

用 IDE 回车,生成 getter / setter

结果生成了这些方法:

你发现了吗?

  • getter 叫 getDeleted()
  • setter 叫 setDeleted()
  • 字段却是 isDeleted

已经开始不统一了。


3️⃣ 一旦字段是 Boolean(不是 boolean)

代码会变得更神奇。

java 复制代码
private Boolean isDeleted;

有些 IDE 会生成:

java 复制代码
public Boolean getIsDeleted() { ... }
public void setIsDeleted(Boolean isDeleted) { ... }

于是项目里开始出现三种名字:

  • isDeleted(字段)
  • isDeleted()(方法)
  • getIsDeleted()(方法)

这时候你再接上 MyBatis / Jackson / Swagger / Lombok,乐子就来了。


三、为什么框架不喜欢 is 前缀?

1️⃣ Java Bean 规范,本身就有点偏执

在 Java Bean 规范里:

  • boolean 类型的 getter,可以是 isXxx()
  • 但 Xxx 本身不应该再带 is

规范推荐的是:

java 复制代码
private boolean deleted;

public boolean isDeleted() { ... }

而不是:

java 复制代码
private boolean isDeleted;
public boolean isIsDeleted() { ... } 

虽然 IDE 会帮你兜底,但规范层面就是反着来的。


2️⃣ JSON 映射时,名字会偷偷变

看一个常见例子:

java 复制代码
private boolean isDeleted;

用 Jackson 转 JSON,结果可能是:

json 复制代码
{
  "deleted": true
}

也可能是:

json 复制代码
{
  "isDeleted": true
}

取决于:字段、getter 名、注解和Jackson 版本

同一个字段,在不同项目里表现不一样。

这不是 bug,这是规范 + 约定 + 实现差异的组合。


3️⃣ 数据库字段更尴尬

数据库里你一般会这样建字段:

sql 复制代码
is_deleted tinyint(1)

Java 里你写:

java 复制代码
private Boolean isDeleted;

ORM 映射时:

  • 有人映射 is_deleted → isDeleted
  • 有人映射 is_deleted → deleted

团队里如果没有统一约定,很快容易会乱。


四、is 会让语义变模糊

这是我个人觉得最致命的一点。

来看这几个变量名:

java 复制代码
isDeleted
isEnable
isSuccess
isUsed

你仔细想一想:

  • isDeleted = true:已删除?还是需要删除?
  • isEnable = false:当前不可用?还是不允许启用?
  • isSuccess = false:操作失败?还是还没执行?

is 很容易让状态和动作意图混在一起。

而如果换成这样:

java 复制代码
deleted
enabled
success
used

搭配方法:

java 复制代码
if (user.isDeleted()) { ... }
if (!account.isEnabled()) { ... }

语义反而更自然。


五、推荐的写法

布尔命名,其实可以分三类。

1、表示状态的

这种是最标准、最推荐的写法。

java 复制代码
private boolean deleted;
private boolean enabled;
private boolean active;
private boolean locked;

对应方法:

java 复制代码
public boolean isDeleted() { ... }
public boolean isEnabled() { ... }

特点:

  • 字段是"状态"
  • getter 用 isXxx()
  • 读起来像一句自然语言

比如:

java 复制代码
if (user.isDeleted())

翻译成中文就是:用户是删除状态吗?非常顺。


2、表示是否拥有的用 has 前缀

有些布尔值表达的不是状态,而是是否拥有某种东西。

比如:

java 复制代码
private boolean hasPermission;
private boolean hasChildren;
private boolean hasLogin;

getter:

java 复制代码
public boolean hasPermission() { ... }
public boolean hasChildren() { ... }

这种语义就更自然:

java 复制代码
if (user.hasPermission())

读起来就是:用户有没有权限?

比:

java 复制代码
if (user.isHasPermission())

自然太多了。


3、表示能力的用 can 前缀

如果表达的是能不能做某件事,用 can 也比 is 更清晰。

java 复制代码
private boolean canEdit;
private boolean canDelete;
private boolean canExport;

使用:

java 复制代码
if (user.canDelete())

这时候它表达的不是状态,而是能力判断。

和:

java 复制代码
if (user.isDelete())

完全不是一个层级的语义。


六、不推荐的写法

java 复制代码
private boolean isDeleted;
private Boolean isEnable;
private boolean isHasPermission;
private boolean isCanEdit;

问题在于:

  • 语义重复
  • getter 容易变成奇怪形式
  • 框架解析可能不一致
  • 可读性下降

尤其是:

java 复制代码
isHasPermission
isCanEdit

读起来非常的拧巴。


七、之前经历

以前一个项目里,有两个字段:

java 复制代码
private Boolean isValid;
private Boolean valid;

一个是历史字段,一个是新字段。

代码里经常出现:

java 复制代码
if (user.isValid()) { ... }
if (user.getIsValid()) { ... }

新来的同事问我:这两个有什么区别?

我当场沉默了 3 秒。不是新同事不行,是命名真的有问题。

本文首发于公众号:程序员大华,专注前端、Java开发,AI应用和工具的分享。关注我,少走弯路,一起进步!

相关推荐
kingx32 分钟前
Bugku 3122 谷歌小恐龙题解:纯离线逆向 Vault 的 AES-GCM 加密资源(附 Python 解密器)
java·逆向·ctf·bugku·aes-gcm
DevOpenClub2 小时前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
露天赏雪3 小时前
第3篇:Sentinel熔断降级实战:大模型接口抖动时的服务兜底方案
java·开发语言·人工智能·spring boot·spring·servlet·sentinel
天天被压力3 小时前
【A股分钟级高频数据完全手册 #06】北交所分钟级数据接口:京市股票Pro版最新分时
java·人工智能·python
天天被压力3 小时前
【A股分钟级高频数据完全手册 #05】指数历史分钟数据接口:Pro版沪深指数分时回放
java·人工智能·python
captain3764 小时前
▲统一功能——DispatcherServlet源码分析
java·spring·java-ee·log4j·maven
金銀銅鐵4 小时前
JDK 21 中 List.of 的实现细节:从 List12 到 ListN
java·后端·ai编程
yeccheng5 小时前
MySQL 索引超详解:从底层 B+ 树到面试高频考点
java·开发语言·jvm·mysql·面试
这个昵称不容易6 小时前
SpringBoot 读书笔记共享平台部署实战:97 个 Java 文件 / 113 个接口 / 10 张表
java·springboot·毕设
金銀銅鐵8 小时前
一个 Java 文件实现《孫子兵法·始計篇》中英对照阅读器
java·后端·ai编程