在日常開發中,我們會經常要在類中定義布爾類型的變量,比如在給外部系統提供一個RPC接口的時候,我們一般會定義一個字段表示本次請求是否成功的。
關于這個”本次請求是否成功”的字段的定義,我見過很多不同的開發者,定義的方式都不同,尤其是在屬性的命名上,有人用 success,有人用 isSuccess 表示。
從語義上面來講,兩種命名方式都可以講的通,并且也都沒有歧義。那么還有什么原則可以參考來讓我們做選擇呢。
根據JavaBeans Specification規定,如果是普通的參數propertyName,要以以下方式定義其setter/getter:
publicget();
publicvoidset(a);
但是,布爾類型的變量propertyName則是單獨定義的:
publicbooleanis();
publicvoidset(booleanm);
success方法的 getter 應該是isSuccess/getSuccess,而isSuccess的getter 應該是isIsSuccess/getIsSuccess。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
但是很多人,在使用isSuccess作為屬性名的時候,還是會采用isSuccess/getSuccess作為 getter 方法名,尤其是現在的很多 IDE 在默認生成 getter 的時候也是會生成isSuccess。
在一般情況下,其實是沒有影響的。但是有一種特殊情況就會有問題,那就是發生序列化的時候可能會導致參數轉換異常。
我們先來定義一個 JavaBean:
classModelimplementsSerializable{
privatestaticfinallongserialVersionUID=1836697963736227954L;
privatebooleanisSuccess;
publicbooleanisSuccess(){
returnisSuccess;
}
publicvoidsetSuccess(booleansuccess){
isSuccess=success;
}
publicStringgetHollis(){
return"yudaoyuanma";
}
}
在這個 JavaBean 中,有一個成員變量isSuccess,三個方法,分別是IDE幫我們自動生成的isSuccess和setSuccess,另外一個是作者自己增加的一個符合getter命名規范的方法。
我們分別使用不同的 JSON 序列化工具來對這個類的對象進行序列化和反序列化:
publicclassBooleanMainTest{
publicstaticvoidmain(String[]args)throwsIOException{
//定一個Model類型
Modelmodel=newModel();
model.setSuccess(true);
//使用fastjson(1.2.16)序列化model成字符串并輸出
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)序列化model成字符串并輸出
ObjectMapperom=newObjectMapper();
System.out.println("SerializableResultWithjackson:"+om.writeValueAsString(model));
}
}
以上代碼輸出結果:
SerializableResultWithfastjson:{"yudao":"yudaoyuanma","success":true}
SerializableResultWithGson:{"isSuccess":true}
SerializableResultWithjackson:{"success":true,"yudao":"yudaoyuanma"}
在fastjson和jackson的結果中,原來類中的isSuccess字段被序列化成success,并且其中還包含yudao值。而Gson中只有isSuccess字段。
我們可以得出結論:fastjson和jackson在把對象序列化成json字符串的時候,是通過反射遍歷出該類中的所有getter方法,得到getHollis和isSuccess,然后根據JavaBeans規則,他會認為這是兩個屬性yudao和success的值。直接序列化成json:
{“yudao”:”yudaoyuanma”,”success”:true}
但是Gson并不是這么做的,他是通過反射遍歷該類中的所有屬性,并把其值序列化成json:
{“isSuccess”:true}
可以看到,由于不同的序列化工具,在進行序列化的時候使用到的策略是不一樣的 ,所以,對于同一個類的同一個對象的序列化結果可能是不同的。那么,如果我們把一個對象使用fastjson進行序列化,再使用Gson反序列化會發生什么呢?
publicclassBooleanMainTest{
publicstaticvoidmain(String[]args)throwsIOException{
Modelmodel=newModel();
model.setSuccess(true);
Gsongson=newGson();
System.out.println(gson.fromJson(JSON.toJSONString(model),Model.class));
}
}
以上代碼,輸出結果:
Model[isSuccess=false]
這和我們預期的結果完全相反,原因是因為JSON框架通過掃描所有的getter后發現有一個isSuccess方法,然后根據JavaBeans的規范,解析出變量名為success,把model對象序列化城字符串后內容為{"success":true}。
根據{"success":true}這個json串,Gson框架在通過解析后,通過反射尋找Model類中的success屬性,但是Model類中只有isSuccess屬性,所以,最終反序列化后的Model類的對象中,isSuccess則會使用默認值false。
但是,一旦以上代碼發生在生產環境,這絕對是一個致命的問題。
所以,作為開發者,我們應該想辦法盡量避免這種問題的發生。
所以,建議大家使用success而不是 isSuccess 這種形式。 這樣,該類里面的成員變量時success,getter方法是isSuccess,這是完全符合JavaBeans規范的。無論哪種序列化框架,執行結果都一樣。就從源頭避免了這個問題。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
-
接口
+關注
關注
33文章
8638瀏覽量
151375 -
參數
+關注
關注
11文章
1839瀏覽量
32289 -
RPC
+關注
關注
0文章
111瀏覽量
11540
原文標題:新來個技術總監:誰在用isXxx形式定義布爾類型年后不用來了
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論