首页 > 编程语言 >Java开发手册中为什么禁止使用isSuccess作为布尔类型变量名以及POJO中基本类型与包装类型的使用标准

Java开发手册中为什么禁止使用isSuccess作为布尔类型变量名以及POJO中基本类型与包装类型的使用标准

时间:2023-06-06 11:12:17浏览次数:57  
标签:Java success 数据类型 POJO isSuccess boolean 类型 public

场景

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

相关文章

  • 44基于java的汽车销售管理系统设计与实现
    本章节给大家带来一个基于java的汽车销售管理系统设计与实现,车辆4S店管理系统,基于java汽车销售交易网站,针对汽车销售提供客户信息、车辆信息、订单信息、销售人员管理、财务报表等功能,提供经理和销售两种角色进行管理。引言实现一个汽车销售管理系统,汽车销售管理系统是一个大......
  • 【HarmonyOS】关于 Caused by java.lang.IllegalStateException The specified...
    【问题描述】线上收到大量手机的崩溃异常,以华为手机为主,崩溃如下1.Causedby:java.lang.IllegalStateException:Thespecifiedmessagequeuesynchronizationbarriertokenhasnotbeenpostedorhasalreadybeenremoved.2.atandroid.os.MessageQueue.removeSyncBarri......
  • From Java To Kotlin 2:Kotlin 类型系统与泛型
    上期主要分享了FromJavaToKotlin1:空安全、扩展、函数、Lambda。这是FromJava toKotlin 第二期。FromJava toKotlin 关键在于思维的转变。表达式思维Kotlin中大部分语句是表达式。表达式思维是一种编程思维。编程思维是一种非常抽象的概念,很多时候是只......
  • javascript笔记
    javascript笔记获得焦点onfocus,失去焦点onblurisNaN()判断是非数字undefined和数字相加最后的结果是NaNnull和数字相加最后的结果是数字typeof空格变量名或typeof(变量名)可以检测变量的类型parseInt('120.8px')最后的结果是120->数字;自动去掉px......
  • 43基于java的校园社团管理系统设计与实现
    本章节给大家带来一个基于java的校园社团管理系统设计与实现,可适用于校园社团管理系统,社团招新管理系统,社团管理系统,社团活动管理系统,高校学生社团,大学社团,学生社团招新,学生社团系统等等;引言校园社团作为高校课外活动的重要组成部分,发展十分迅速,也受到越来越多学生的欢迎,社团......
  • Dapr在Java中的实践 之 服务调用
    服务调用通过服务调用(Service-to-serviceInvocation),服务可以使用gRPC或HTTP这样的标准协议来发现并可靠地与其他服务通信。Dapr采用边车(Sidecar)、去中心化的架构。要使用Dapr来调用服务,可以在任意Dapr实例上使用invoke这个API。边车编程模型鼓励每个服务与自己的Dapr实例......
  • Java-Day-27( Properties 类 + 章节练习 )
    Java-Day-27Properties类程序读取xx.properties配置文件,修改的话就通过配置文件将信息写入到程序(非写死在程序中,灵活性差,编译代价大)传统方法:publicclassTest{publicstaticvoidmain(String[]args)throwsIOException{//传统方法//读取db.......
  • Java官方笔记7接口
    接口接口只能包含:constants,methodsignatures(abstract),defaultmethods,staticmethods,andnestedtypes方法体只存在于:defaultmethodsandstaticmethods接口不能实例化,只能被类实现,或者被其他接口继承(接口可以多继承)。定义接口:publicinterfaceOperateCar{/......
  • 【Java】再谈Springboot 策略模式
     第一次使用策略模式是一年前的一个项目:https://www.cnblogs.com/mindzone/p/16046538.html当时还不知道Spring支持集合类型的自动装配在最近一个项目,我发现很多业务需要频繁的使用这种模式去聚合代码 一、牛刀小试这是最开始的定义策略的业务接口/***业务推送管......
  • TypeScript Vs JavaScript 区别
    一、观察1.JS平常的复制类型letval;val=123;val="123";val=true;val=[1,3,5];注意点:由于JS是弱类型的,所以只要定义了一个变量,就可以往这个变量中存储任意类型的数据也正是因为如此,所以会给我们带来一个问题2.假设a是一个数组,b是一个数值func......