场景
Java开发手册中关于POJO的布尔类型的变量名的要求是:
【强制】POJO 类中的任何布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。
说明:在本文 MySQL 规约中的建表约定第一条,表达是与否的变量采用 is_xxx 的命名方式,所以,需要
在<resultMap>设置从 is_xxx 到 xxx 的映射关系。
反例:定义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted(),框架在反向解析的时候,
“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。
下面来验证下上面的结论。
在日常开发中,我们会经常要在类中定义布尔类型的变量,比如在给外部系统提供一个 RPC 接口的时候,
我们一般会定义一个字段表示本次请求是否成功的。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
我们先新建以下四个POJO
Model1 :
public class Model1 { private Boolean isSuccess; public Boolean getSuccess() { return isSuccess; } public void setSuccess(Boolean success) { isSuccess = success; } }
Model2 :
public class Model2 { private Boolean success; public Boolean getSuccess() { return success; } public void setSuccess(Boolean success) { this.success = success; } }
Model3:
public class Model3 { private boolean isSuccess; public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean success) { isSuccess = success; } }
Model4 :
public class Model4 { private boolean success; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } }
以上四个POJO都是通过IDEA自动生成的get和set方法,可以看到:
基本类型自动生成的 getter 和 setter 方法,名称都是isXXX()和setXXX()形式的。
包装类型自动生成的getter和setter方法,名称都是getXXX()和setXXX()形式的
JavaBean 中关于 setter/getter 的规范
关于 Java Bean 中的 getter/setter 方法的定义其实是有明确的规定的,根据JavaBeans(TM) Specification规定:
https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/
如果是普通的参数 propertyName,要以以下方式定义其 setter/getter:
public <PropertyType>
get<PropertyName>();
public void
set<PropertyName>(<PropertyType> a);
但是,布尔类型的变量 propertyName 则是单独定义的:
public boolean is<PropertyName>();
public void set<PropertyName>(boolean m);
通过对照这份 JavaBeans 规范,我们发现,在 Model4 中,变量名为 isSuccess,如果严格按照规范定义的话,
其getter 方法应该叫 isIsSuccess。但是很多IDE 都会默认生成为 isSuccess。
Java中fastJson、jackson、Gson对于POJO的布尔变量isSuccess序列化的影响
拿常用的序列化进行举例,如果需要引入依赖,根据自己项目情况自行引入
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.9</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.12.0</version> </dependency>
引入依赖之后,示例代码如下:
Model3 model3 = new Model3(); model3.setSuccess(true); System.out.println("Serialiazable Result with fashjson:"+com.alibaba.fastjson.JSON.toJSONString(model3)); com.google.gson.Gson gson = new Gson(); System.out.println("Serialiazable Result with Gson:"+gson.toJson(model3)); com.fasterxml.jackson.databind.ObjectMapper om = new ObjectMapper(); System.out.println("Serialiazable Result with jackson:"+om.writeValueAsString(model3));
以上代码的输出结果为
//Serialiazable Result with fashjson:{"success":true} //Serialiazable Result with Gson:{"isSuccess":true} //Serialiazable Result with jackson:{"success":true}
可以看到
在 fastjson 和 jackson 的结果中,原来类中的 isSuccess 字段被序列化成success。
而 Gson 中是 isSuccess 字段。
fastjson 和 jackson 在把对象序列化成 json 字符串的时候,是通过反射遍历出该类中的所有 getter 方法,
得到isSuccess,然后根据 JavaBeans 规则,他会认为这是属性success的值。直接序列化成 json:{"success":true}
但是 Gson 并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成 json:{“isSuccess”:true}
可以看到,由于不同的序列化工具,在进行序列化的时候使用到的策略是不一样的,
所以,对于同一个类的同一个对象的序列化结果可能是不同的。
如果对于同一个对象,使用fastjson进行序列化,再使用Gson反序列化会发生什么?
测试代码如下:
System.out.println(gson.fromJson(com.alibaba.fastjson.JSON.toJSONString(model3),Model3.class).isSuccess());
以上输出结果为false
原因是因为 JSON 框架通过扫描所有的 getter后发现有一个isSuccess方法,然后根据JavaBeans的规范,解析出变量名为success,
把 model 对象序列化城字符串后内容为{"success":true}。根据{"success":true}这个 json 串,
Gson 框架在通过解析后,通过反射寻找 Model 类中的 success 属性,
但是 Model 类中只有 isSuccess 属性,所以,最终反序列化后的 Model 类的对象中,isSuccess 则会使用默认值 false。
所以,在定义 POJO 中的布尔类型的变量时,不要使用 isSuccess 这种形式,而要直接使用 success !
Java的POJO中布尔变量使用基本数据类型boolean还是包装数据类型Boolean
新建一个POJO
import java.util.StringJoiner; public class Model { private Boolean success; private boolean failure; public Boolean getSuccess() { return success; } public void setSuccess(Boolean success) { this.success = success; } public boolean isFailure() { return failure; } public void setFailure(boolean failure) { this.failure = failure; } @Override public String toString() { return new StringJoiner(",",Model.class.getSimpleName()+"[","]") .add("success = "+success) .add("failure= "+failure) .toString(); } }
并使用Java 8的StringJoiner重写toString方法。
然后输出该对象的toString
Model model = new Model(); System.out.println("default model: "+model);
以上代码输出结果
default model: Model[success = null,failure= false]
可以看到,当我们没有设置 Model 对象的字段的值的时候,Boolean 类型的变量会设置默认值为null,
而 boolean 类型的变量会设置默认值为false。即对象的默认值是null,boolean 基本数据类型的默认值是false。
在 Java 开发手册中,对于 POJO 中如何选择变量的类型也有着一些规定
关于基本数据类型与包装数据类型的使用标准如下:
1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
3) 【推荐】所有的局部变量使用基本数据类型。
说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。
正例:
数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
反例:
某业务的交易报表上显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调
用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线-。所以包装数据类型
的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。
标签:Java,success,数据类型,POJO,isSuccess,boolean,类型,public From: https://www.cnblogs.com/badaoliumangqizhi/p/17459980.html