平时工作中大家经常使用到 boolean 以及 Boolean 类型的数据,前者是基本数据类型,后者是包装类,为什么不推荐使用 isXXX 来命名呢?到底是用基本类型的数据好呢还是用包装类好呢?
为什么不推荐使用 isXXX 来命名布尔类型的数据
其实阿里巴巴发布的 Java 开发手册中就写明了,强制规定,布尔类型的数据,无论是 boolean 还是 Boolean 都不准使用 isXXX 来命名。

为了测试出结果,我创建了四个实体类,分别定义了不同的属性,boolean testBoolean、boolean isTestBoolean、
Boolean testBoolean、Boolean isTestBoolean,结果如下:


从图上可以看出:
- 基本数据类型自动生成的 getter 和 setter 方法的名称都是 isXXX() 和 setXXX()
- 包装类自动生成的 getter 和 setter 方法的名称都是 getXXX() 和 setXXX()
其实 JavaBeans 规范中对这些均有相应的规定,基本数据类型的属性,其 getter 和 setter 方法是 getXXX() 和 setXXX,但是对于基本数据中布尔类型的数据,又有一套规定,其 getter 和 setter 方法是 isXXX() 和 setXXX,感兴趣的同学可以自己搜搜这个规范看看,这里我就不贴出来了。
平时使用的时候可能不会出什么问题,但是在 Json 序列化对象的时候就会出问题,比如 Gson、FastJson、JackJson。当这三个工具对对象进行序列化时,Gson 只会通过反射遍历获取到属性,然后将其值进行序列化,但是 FastJson 和 JackJson 是反射遍历获取对象的 getter 方法,然后会通过相应的 JavaBeans 规则,认为 getXXX 或者 isXXX 后面就是属性,然后进行序列化。
所以使用 isXXX 来定义属性名字的,通过 JackJson 和 FastJson 序列化出来的结果,总是比通过 Gson 序列化出来的结果多一个属性。我们就以 TestBoolean1 和 TestBoolean2 进行序列化来对比结果:


从图可以看出:若不使用的 isXXX 来定义属性名,三个工具序列化的结果一样的,这没什么问题。
下面是命名为 isXXX 的属性,序列化以后的结果如下:


可以看出,序列化后的结果如上,会发现 Gson 序列化后的结果跟 JackJson 以及 FastJson 的结果不一致。说到底还是序列化的方式不同,那么问题就来了,当设置 isTestBoolean 为 true,当使用 FastJson 进行序列化以后再通过 Gson 进行反序列化,结果就会出问题:


你会发现本来给 isTestBoolean 赋值的是 true,但是反序列化以后的结果是 false,跟我们想要的结果不一致。
究其原因,FastJson 通过反射遍历找到 isTestBoolean 方法,基于 JavaBeans 规范,认为这个类的属性是 testBoolean,然后获取其值,将其序列化为 {"testBoolean",true},然后 Gson 解析字符串,通过 testBoolean 找该类的属性,结果发现该类就一个属性 isTestBoolean,没有 testBoolean 属性。
因此 Gson 反序列化后 TestBoolean2 中的 isTestBoolean 会使用其默认值 false,而不是我们想要的 true。因此,阿里巴巴的 Java 开发手册强制规定,布尔类型的数据,不要用 isXXX 来命名。
工作中使用基本类型的数据好还是包装类好
咱们举个例子,一个计算盈利的系统,其盈利比例有正有负,若使用了基本类型 double 定义了数据,当 RPC 调用时,若出现了问题,本来应该返回错误的,但是由于使用了基本类型,返回了 0.0,系统会认为没有任何问题,今年收支平衡,而不会发现其实是出现了错误。
若使用了包装数据类型 Double,当 RPC 调用失败时,会返回null,这样直接就能看到出现问题了,而不会因为默认值的问题影响判断。
其实阿里 Java 开发手册中对于这个也有强制规定:

因此,这里建议大家 POJO 中使用包装数据类型,局部变量使用基本数据类型。