当前位置: 首页 > 科技观察

一个新的技术总监:谁用isXxx的形式定义布尔类型,一年后就不会用了

时间:2023-03-12 13:34:30 科技观察

在日常开发中,我们经常需要在一个类中定义布尔类型的变量,比如为类提供一个RPC接口外部系统有时候,我们一般会定义一个字段来表示请求是否成功。关于“本次请求是否成功”字段的定义,我见过很多不同的开发者,定义的方式也不尽相同,尤其是在属性的命名上,有的人用success,有的人用isSuccess来表示。从语义上来说,两种命名方式都是合理的,没有歧义。那么我们还有哪些原则可以参考让我们做出选择呢?根据JavaBeansSpecification,如果是一个普通的参数propertyName,那么它的setter/getter应该这样定义:publicget();publicvoidset(a);但是,布尔类型的变量propertyName是单独定义的:publicbooleanis();publicvoidset(booleanm);success方法的getter应该是isSuccess/getSuccess,isSuccess的getter应该是isIsSuccess/getIsSuccess。但是很多人在使用isSuccess作为属性名的时候,仍然使用isSuccess/getSuccess作为getter方法名,尤其是很多IDE默认生成getter的时候,也会生成isSuccess。总的来说,其实没什么影响。但是有一种特殊情况会出现问题,就是在进行序列化时,可能会出现参数转换异常。我们先来定义一个JavaBean:classModelimplementsSerializable{privatestaticfinallongserialVersionUID=1836697963736227954L;privatebooleanisSuccess;publicbooleanisSuccess(){returnisSuccess;}publicvoidsetSuccess(booleansuccess){isSuccess=success;}publicStringgetHollis(){return"hollischuang";}}在这个JavaBean中,有一个成员变量isSuccess有3个方法,一个是IDE自动为我们生成的isSuccess和setSuccess,另一个是作者自己添加的符合getter命名规范的方法。我们使用不同的JSON序列化工具来序列化和反序列化这个类的对象:1.2.16)将模型序列化为字符串并输出System.out.println("SerializableResultWithfastjson:"+JSON.toJSONString(model));//使用Gson(2.8.5)将Model序列化为字符串并输出Gsongson=newGson();System.out.println("SerializableResultWithGson:"+gson.toJson(model));//使用jackson(2.9.7)将模型序列化为字符串输出ObjectMapperom=newObjectMapper();System.out.println("SerializableResultWithjackson:"+om.writeValueAsString(model));}}以上代码输出结果:SerializableResultWithfastjson:{"hollis":"hollishuang","success":true}SerializableResultWithGson:{"isSuccess":true}SerializableResultWithjackson:{"success":true,"hollis":"hollishuang"}在fastjson和jackson的结果中,将原类中的isSuccess字段序列化为success,同时也包含了hollis值。而Gson只有isSuccess字段。我们可以得出一个结论:fastjson和jackson在将对象序列化成json字符串的时候,是通过反射遍历类中所有的getter方法得到getHollis和isSuccess,然后根据JavaBeans的规则,他会认为这是两个的值hollis和success属性。直接序列化成json:{"hollis":"hollishuang","success":true}但是Gson不会这样做,他通过反射遍历类中的所有属性,将其值序列化成json:{"isSuccess":true可以看到,由于序列化工具不同,序列化使用的策略不同,所以同一个类的同一个对象的序列化结果可能是不一样的。Gson?publicclassBooleanMainTest{publicstaticvoidmain(String[]args)throwsIOException{Modelmodel=newModel();model.setSuccess(true);Gsongson=newGson();System.out.println(gson.fromJson(JSON.toJSONString(model),模型.class));}}上面的代码,输出结果:Model[isSuccess=false]这和我们预期的结果恰好相反,原因是JSON框架扫描了所有的getter后发现了一个isSuccess方法,然后根据JavaBeans解析出变量名success规范,将模型对象序列化为字符串,内容为{"success":true}。Gson框架根据json字符串{"success":true},解析后通过反射找到Model类中的success属性,但是Model类中只有isSuccess属性,所以,在最终反序列化的Model类对象中,isSuccess将使用默认值false。但是,一旦在生产环境中出现上面的代码,这绝对是一个致命的问题。因此,作为开发者,我们应该想办法尽可能避免此类问题的发生。所以建议大家使用success的形式,不要使用isSuccess。这样,该类中的成员变量为success,getter方法为isSuccess,完全符合JavaBeans规范。无论使用何种序列化框架,执行结果都是一样的。只是从源头上避免这个问题。