广告
返回顶部
首页 > 资讯 > 精选 >为什么不使用isSuccess作为变量名
  • 221
分享到

为什么不使用isSuccess作为变量名

2023-06-04 08:06:21 221人浏览 泡泡鱼
摘要

本篇内容介绍了“为什么不使用isSuccess作为变量名”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在日常开发中,我们会经常要在类中定义布

本篇内容介绍了“为什么不使用isSuccess作为变量名”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

在日常开发中,我们会经常要在类中定义布尔类型的变量,比如在给外部系统提供一个rpc接口的时候,我们一般会定义一个字段表示本次请求是否成功的。

关于这个”本次请求是否成功”的字段的定义,其实是有很多种讲究和坑的,稍有不慎就会掉入坑里,作者在很久之前就遇到过类似的问题,本文就来围绕这个简单分析一下。到底该如何定一个布尔类型的成员变量。

一般情况下,我们可以有以下四种方式来定义一个布尔类型的成员变量:

boolean success
boolean isSuccess
Boolean success
Boolean isSuccess

以上四种定义形式,你日常开发中最常用的是哪种呢?到底哪一种才是正确的使用姿势呢?

通过观察我们可以发现,前两种和后两种的主要区别是变量的类型不同,前者使用的是boolean,后者使用的是Boolean。

另外,第一种和第三种在定义变量的时候,变量命名是success,而另外两种使用isSuccess来命名的。

首先,我们来分析一下,到底应该是用success来命名,还是使用isSuccess更好一点。

success 还是 isSucces
为什么不使用isSuccess作为变量名

到底应该是用success还是isSuccess来给变量命名呢?从语义上面来讲,两种命名方式都可以讲的通,并且也都没有歧义。那么还有什么原则可以参考来让我们做选择呢。

在阿里巴巴Java开发手册中关于这一点,有过一个『强制性』规定:

为什么不使用isSuccess作为变量名
那么,为什么会有这样的规定呢?我们看一下POJO中布尔类型变量不同的命名有什么区别吧。

class Model1  {
   private Boolean isSuccess;
   public void setSuccess(Boolean success) {
       isSuccess = success;
   }
   public Boolean getSuccess() {
       return isSuccess;
   }
}

class Model2 {
   private Boolean success;
   public Boolean getSuccess() {
       return success;
   }
   public void setSuccess(Boolean success) {
       this.success = success;
   }
}

class Model3 {
   private boolean isSuccess;
   public boolean isSuccess() {
       return isSuccess;
   }
   public void setSuccess(boolean success) {
       isSuccess = success;
   }
}

class Model4 {
   private boolean success;
   public boolean isSuccess() {
       return success;
   }
   public void setSuccess(boolean success) {
       this.success = success;
   }
}

以上代码的setter/getter是使用Intellij idea自动生成的,仔细观察以上代码,你会发现以下规律:

  • 基本类型自动生成的getter和setter方法,名称都是isXXX()setXXX()形式的。

  • 包装类型自动生成的getter和setter方法,名称都是getXXX()setXXX()形式的。

既然,我们已经达成一致共识使用基本类型boolean来定义成员变量了,那么我们再来具体看下Model3和Model4中的setter/getter有何区别。

3y:看到这里的同学可能有点懵,为啥这里说“已经达成一致共识使用基本类型boolean来定义成员变量” 。其实原作者就这篇文章写了两篇。至于为什么原作者赞同使用基本数据类型,可以看为什么赞同boolean使用基本数据类型。本文的后面也有相应解释。

我们可以发现,虽然Model3和Model4中的成员变量的名称不同,一个是success,另外一个是isSuccess,但是他们自动生成的getter和setter方法名称都是isSuccesssetSuccess

Java Bean中关于setter/getter的规范

关于Java Bean中的getter/setter方法的定义其实是有明确的规定的,根据JavaBeans(TM) Specification规定,如果是普通的参数,命名为propertyName,需要通过以下方式定义其setter/getter:

public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);

但是,布尔类型的变量propertyName则是另外一套命名原则的:

public boolean is<PropertyName>();
public void set<PropertyName>(boolean m);

为什么不使用isSuccess作为变量名

通过对照这份JavaBeans规范,我们发现,在Model4中,变量名为isSuccess,如果严格按照规范定义的话,他的getter方法应该叫isIsSuccess。但是很多IDE都会默认生成为isSuccess。

那这样做会带来什么问题呢。

在一般情况下,其实是没有影响的。但是有一种特殊情况就会有问题,那就是发生序列化的时候。

序列化带来的影响

关于序列化和反序列化请参考Java对象的序列化与反序列化。我们这里拿比较常用的JSON序列化来举例,看看常用的fastjson、jackson和Gson之间有何区别:

public class BooleanMainTest {

   public static void main(String[] args) throws IOException {
       //定一个Model3类型
       Model3 model3 = new Model3();
       model3.setSuccess(true);

       //使用fastjson(1.2.16)序列化model3成字符串并输出
       System.out.println("Serializable Result With fastjson :" + JSON.toJSONString(model3));

       //使用Gson(2.8.5)序列化model3成字符串并输出
       Gson gson =new Gson();
       System.out.println("Serializable Result With Gson :"+gson.toJson(model3));

       //使用jackson(2.9.7)序列化model3成字符串并输出
       ObjectMapper om = new ObjectMapper();
       System.out.println("Serializable Result With jackson :" +om.writeValueAsString(model3));
   }
}

class Model3 implements Serializable {

   private static final long serialVersionUID = 1836697963736227954L;
   private boolean isSuccess;
   public boolean isSuccess() {
       return isSuccess;
   }
   public void setSuccess(boolean success) {
       isSuccess = success;
   }
   public String getHollis(){
       return "hollischuang";
   }
}

以上代码的Model3中,只有一个成员变量即isSuccess,三个方法,分别是IDE帮我们自动生成的isSuccess和setSuccess,另外一个是作者自己增加的一个符合getter命名规范的方法。

以上代码输出结果:

Serializable Result With fastjson :{"hollis":"hollischuang","success":true}
Serializable Result With Gson :{"isSuccess":true}
Serializable Result With jackson :{"success":true,"hollis":"hollischuang"}

在fastjson和jackson的结果中,原来类中的isSuccess字段被序列化成success,并且其中还包含hollis值。而Gson中只有isSuccess字段。

我们可以得出结论:fastjson和jackson在把对象序列化成json字符串的时候,是通过反射遍历出该类中的所有getter方法,得到getHollis和isSuccess,然后根据JavaBeans规则,他会认为这是两个属性hollis和success的值。直接序列化成json:

{“hollis”:”hollischuang”,”success”:true}

但是Gson并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成json:

{“isSuccess”:true}

可以看到,由于不同的序列化工具,在进行序列化的时候使用到的策略是不一样的,所以,对于同一个类的同一个对象的序列化结果可能是不同的。

前面提到的关于对getHollis的序列化只是为了说明fastjson、jackson和Gson之间的序列化策略的不同,我们暂且把他放到一边,我们把他从Model3中删除后,重新执行下以上代码,得到结果:

Serializable Result With fastjson :{"success":true}
Serializable Result WithGson :{"isSuccess":true}
Serializable Result With jackson :{"success":true}

现在,不同的序列化框架得到的json内容并不相同,如果对于同一个对象,我使用fastjson进行序列化,再使用Gson反序列化会发生什么?

public class BooleanMainTest {
   public static void main(String[] args) throws IOException {
       Model3 model3 = new Model3();
       model3.setSuccess(true);
       Gson gson =new Gson();
       System.out.println(gson.fromJson(JSON.toJSONString(model3),Model3.class));
   }
}

class Model3 implements Serializable {
   private static final long serialVersionUID = 1836697963736227954L;
   private boolean isSuccess;
   public boolean isSuccess() {
       return isSuccess;
   }
   public void setSuccess(boolean success) {
       isSuccess = success;
   }
   @Override
   public String toString() {
       return new StringJoiner(", ", Model3.class.getSimpleName() + "[","]")
           .add("isSuccess=" + isSuccess)
           .toString();
   }
}

以上代码,输出结果:

Model3[isSuccess=false]

这和我们预期的结果完全相反,原因是因为JSON框架通过扫描所有的getter后发现有一个isSuccess方法,然后根据JavaBeans的规范,解析出变量名为success,把model对象序列化城字符串后内容为{"success":true}

根据{"success":true}这个json串,Gson框架在通过解析后,通过反射寻找Model类中的success属性,但是Model类中只有isSuccess属性,所以,最终反序列化后的Model类的对象中,isSuccess则会使用默认值false。

但是,一旦以上代码发生在生产环境,这绝对是一个致命的问题。

所以,作为开发者,我们应该想办法尽量避免这种问题的发生,对于POJO的设计者来说,只需要做简单的一件事就可以解决这个问题了,那就是把isSuccess改为success。

这样,该类里面的成员变量时success,getter方法是isSuccess,这是完全符合JavaBeans规范的。无论哪种序列化框架,执行结果都一样。就从源头避免了这个问题。

引用一下R大关于阿里巴巴Java开发手册中这条规定的评价

为什么不使用isSuccess作为变量名

所以,在定义POJO中的布尔类型的变量时,不要使用isSuccess这种形式,而要直接使用success!

Boolean还是boolean?
为什么不使用isSuccess作为变量名

前面我们介绍完了在success和isSuccess之间如何选择,那么排除错误答案后,备选项还剩下:

boolean success
Boolean success

那么,到底应该是用Boolean还是boolean来给定一个布尔类型的变量呢?

我们知道,boolean是基本数据类型,而Boolean是包装类型。

那么,在定义一个成员变量的时候到底是使用包装类型更好还是使用基本数据类型呢?

我们来看一段简单的代码


public class BooleanMainTest {
   public static void main(String[] args) {
       Model model1 = new Model();
       System.out.println("default model : " + model1);
   }
}

class Model {
   
   private Boolean success;
   
   private boolean failure;

   
   @Override
   public String toString() {
       return new StringJoiner(", ", Model.class.getSimpleName() + "[","]")
           .add("success=" + success)
           .add("failure=" + failure)
           .toString();
   }
}

以上代码输出结果为:

default model : Model[success=null, failure=false]

可以看到,当我们没有设置Model对象的字段的值的时候,Boolean类型的变量会设置默认值为null,而boolean类型的变量会设置默认值为false

即对象的默认值是null,boolean基本数据类型的默认值是false

在阿里巴巴Java开发手册中,对于POJO中如何选择变量的类型也有着一些规定:

为什么不使用isSuccess作为变量名

这里建议我们使用包装类型,原因是什么呢?

举一个扣费的例子,我们做一个扣费系统,扣费时需要从外部的定价系统中读取一个费率的值,我们预期该接口的返回值中会包含一个浮点型的费率字段。当我们取到这个值得时候就使用公式:金额*费率=费用 进行计算,计算结果进行划扣。

如果由于计费系统异常,他可能会返回个默认值,如果这个字段是Double类型的话,该默认值为null,如果该字段是double类型的话,该默认值为0.0。

如果扣费系统对于该费率返回值没做特殊处理的话,拿到null值进行计算会直接报错,阻断程序。拿到0.0可能就直接进行计算,得出接口为0后进行扣费了。这种异常情况就无法被感知。

这种使用包装类型定义变量的方式,通过异常来阻断程序,进而可以被识别到这种线上问题。如果使用基本数据类型的话,系统可能不会报错,进而认为无异常。

“为什么不使用isSuccess作为变量名”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 为什么不使用isSuccess作为变量名

本文链接: https://www.lsjlt.com/news/237020.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 为什么不使用isSuccess作为变量名
    本篇内容介绍了“为什么不使用isSuccess作为变量名”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在日常开发中,我们会经常要在类中定义布...
    99+
    2023-06-04
  • java怎么用类名作为变量类型
    在Java中,类名可以作为变量类型。要使用类名作为变量类型,可以按照以下方式声明变量: ClassName variableName...
    99+
    2023-10-25
    java
  • 为什么不要在 Flutter 中使用全局变量
    目录前言Flutter 中的全局变量是什么?Flutter 中使用全局变量的缺点1. 复杂的代码维护过程2. 全局变量使单元测试变得痛苦3. 全局变量导致“面条&rdqu...
    99+
    2022-11-13
  • python如何使用Dims作为变量
    这篇文章主要为大家展示了“python如何使用Dims作为变量”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何使用Dims作为变量”这篇文章吧。Dims作为变量在大多数语言中,为了...
    99+
    2023-06-27
  • 为什么不使用JS匿名函数
    这篇文章主要讲解了“为什么不使用JS匿名函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“为什么不使用JS匿名函数”吧!如果你不知道匿名函数是什么,这里有一...
    99+
    2022-10-19
  • java环境变量配置为什么不成功
    Java环境变量配置不成功可能有以下几个原因:1. 配置错误:可能配置的路径不正确,或者配置的环境变量名称有误。在配置环境变量时,需...
    99+
    2023-09-08
    java
  • react为什么不推荐使用index作为key
    1.旧的虚拟dom和新的虚拟dom对比,首先看他们的key是否相同 2.相同继续对比他们的内容,不同生成新的真实dom进行替换 3.如果内容和key都相同,复用旧的真实dom 不做改...
    99+
    2022-11-12
  • 域名绑定了为什么不能使用
    域名绑定后却无法使用的原因:1.域名未解析;2.域名解析未生效;3.域名到期;域名绑定后却无法使用的原因有以下几点域名未解析绑定域名后,需要将域名解析到对应的网站,在通过域名访问网站。域名解析未生效域名解析一般都有生效时间,使用通用顶级域名...
    99+
    2022-10-18
  • python中为什么尽量少用全局变量
    这篇文章主要介绍了python中为什么尽量少用全局变量,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。尽量少用全局变量Python查找最快、效率最高的是局部变量,查找全局变量相...
    99+
    2023-06-27
  • 为什么不对分类变量进行独热编码
    本篇内容主要讲解“为什么不对分类变量进行独热编码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“为什么不对分类变量进行独热编码”吧!独热编码(又称虚拟变量)是一种...
    99+
    2022-10-19
  • 为什么MySQL不建议使用NULL作为列默认值?
    1 前言 NULL值是一种对列的特殊约束,我们创建一个新列时,如果没有明确的使用关键字not null声明该数据列,Mysql会默认的为我们添加上NULL约束. 有些开发人员在创建数据表时,由于懒惰直...
    99+
    2023-09-10
    mysql 数据库
  • 在vue中为什么不能用index作为key
    目录一、key的作用是什么?二、什么是虚拟DOM?三、什么是diff算法四、为什么不能用index作为key?(1)index不能作为key--情景一(2)index不能作为key-...
    99+
    2022-11-13
  • 为什么不使用TypeScript
    这篇文章主要为大家展示了“为什么不使用TypeScript”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“为什么不使用TypeScript”这篇文章吧。有风险哇。...
    99+
    2022-10-19
  • 不限流量的美国vps速度为什么会变慢
    不限流量美国vps速度变慢的原因有:1、带宽不足,超过了最大限度的带宽和承载能力,导致美国vps速度变慢;2、系统资源不足,导致程序...
    99+
    2023-02-08
    不限流量的美国vps 美国vps vps
  • android为什么FLAG_ACTIVITY_CLEAR_TOP不起作用
    FLAG_ACTIVITY_CLEAR_TOP标志位用于启动一个新的Activity时,如果该Activity已经在栈中存在,则将其...
    99+
    2023-09-16
    android
  • android – 为什么FLAG_ACTIVITY_CLEAR_TOP不起作用
    FLAG_ACTIVITY_CLEAR_TOP 是一个Intent的标志,用于将Activity任务栈中位于启动Activity之上...
    99+
    2023-09-17
    android
  • 为什么vue中不建议使用空字符串作为className
    目录比较空字符串''和null情况1:使用空字符串''情况2:使用null情况3:使用undefined使用对象的形式绑定class使用 &&绑定class案例1:i...
    99+
    2022-11-12
  • 为什么不能用uuid作为数据库主键
    这篇文章主要介绍“为什么不能用uuid作为数据库主键”,在日常操作中,相信很多人在为什么不能用uuid作为数据库主键问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”为什么不能用...
    99+
    2022-10-18
  • 为什么不使用VS Code
    本篇内容介绍了“为什么不使用VS Code”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!不久前,我大部分的...
    99+
    2022-10-19
  • 为什么不建议使用Java自定义Object作为HashMap的key
    目录前言踩坑历程回顾hashCode覆写的讲究为什么hashCode和equals要同时覆写数据退出机制的兜底总结前言 此前部门内的一个线上系统上线后内存一路飙高、一段时间后直接占满...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作