<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          程序員新人上午使用 isXxx 形式定義布爾類(lèi)型,下午就被勸退?

          共 5595字,需瀏覽 12分鐘

           ·

          2022-06-21 02:54

          二哥編程知識(shí)星球 (戳鏈接加入)正式上線了,來(lái)和 260 多名 小伙伴一起打怪升級(jí)吧!這是一個(gè) Java 學(xué)習(xí)指南 + 編程實(shí)戰(zhàn)的私密圈子,你可以向二哥提問(wèn)、幫你制定學(xué)習(xí)計(jì)劃、跟著二哥一起做實(shí)戰(zhàn)項(xiàng)目,沖沖沖。

          Java 程序員進(jìn)階之路網(wǎng)址:https://tobebetterjavaer.com

          小二是新來(lái)的背鍋俠,哦,不不不,新來(lái)的實(shí)習(xí)生。面試過(guò)程中表現(xiàn)得非常不錯(cuò),各種問(wèn)題對(duì)答如流,老板和我都倍感欣慰。

          這么優(yōu)秀的人,絕不能讓他浪費(fèi)一分一秒,于是很快,我就給他安排了一個(gè)非常簡(jiǎn)單的任務(wù)。

          大家都知道,在日常開(kāi)發(fā)中,我們會(huì)經(jīng)常要在類(lèi)中定義布爾類(lèi)型的變量,比如在給外部系統(tǒng)提供一個(gè) RPC 接口的時(shí)候,我們一般會(huì)定義一個(gè)字段表示本次請(qǐng)求是否成功的。

          關(guān)于這個(gè)”本次請(qǐng)求是否成功”的字段的定義,我見(jiàn)過(guò)很多不同的開(kāi)發(fā)者,定義的方式都不同,尤其是在屬性的命名上,有人用 success,有人用 isSuccess 表示。

          從語(yǔ)義上面來(lái)講,兩種命名方式都可以講的通,并且也都沒(méi)有歧義。

          這不,小二就采用了 isSuccess 的形式來(lái)定義布爾類(lèi)型的變量,于是下午 review 的時(shí)候就被眼尖的老板揪了出來(lái)。老板畢竟是在阿里待過(guò)的,對(duì)這些細(xì)節(jié)扣的很細(xì)。

          于是大發(fā)雷霆,準(zhǔn)備當(dāng)場(chǎng)勸退小二,被我攔了下來(lái)。畢竟自己面試的人,不看僧面看佛面,是吧?于是老板答應(yīng)我說(shuō)再試用一個(gè)月看看。

          isSuccess 會(huì)有什么問(wèn)題呢?小二很是不解。

          那根據(jù) JavaBeans Specification 的規(guī)定,如果是普通的參數(shù) propertyName,要以以下方式定義其 setter/getter:

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

          但是,布爾類(lèi)型的變量 propertyName 則是單獨(dú)定義的:

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

          success 方法的 getter 應(yīng)該是 isSuccess/getSuccess,而 isSuccess 的 getter 應(yīng)該是 isIsSuccess/getIsSuccess。

          但是很多人,在使用 isSuccess 作為屬性名的時(shí)候,還是會(huì)采用 isSuccess/getSuccess 作為 getter 方法名,尤其是現(xiàn)在的很多 IDE 在默認(rèn)生成 getter 的時(shí)候也是會(huì)生成 isSuccess。

          在一般情況下,其實(shí)是沒(méi)有影響的。但是有一種特殊情況就會(huì)有問(wèn)題,那就是發(fā)生序列化的時(shí)候可能會(huì)導(dǎo)致參數(shù)轉(zhuǎn)換異常。

          我們先來(lái)定義一個(gè) JavaBean:

          class Model 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 getWanger(){
                 return "hollis";
             }
          }

          在這個(gè) JavaBean 中,有一個(gè)成員變量 isSuccess,三個(gè)方法,分別是 IDE 幫我們自動(dòng)生成的 isSuccess 和 setSuccess,另外一個(gè)是作者自己增加的一個(gè)符合 getter 命名規(guī)范的方法。

          我們分別使用不同的 JSON 序列化工具來(lái)對(duì)這個(gè)類(lèi)的對(duì)象進(jìn)行序列化和反序列化:

          public class BooleanMainTest {
               public static void main(String[] args) throws IOException {
                   //定一個(gè)Model類(lèi)型
                   Model model = new Model();
                   model.setSuccess(true);
                   
                   //使用fastjson(1.2.16)序列化model成字符串并輸出
                   System.out.println("Serializable Result With fastjson :" + JSON.toJSONString(model));
                   
                   //使用Gson(2.8.5)序列化model成字符串并輸出
                   Gson gson =new Gson();
                   System.out.println("Serializable Result With Gson :" +gson.toJson(model));
                   
                   //使用jackson(2.9.7)序列化model成字符串并輸出
                   ObjectMapper om = new ObjectMapper();
                   System.out.println("Serializable Result With jackson :" +om.writeValueAsString(model));
               }
          }

          以上代碼輸出結(jié)果:

          Serializable Result With fastjson :{"wanger":"hollis","success":true}

          Serializable Result With Gson :{"isSuccess":true}

          Serializable Result With jackson :{"success":true,"wanger":"hollis"}

          在 fastjson 和 jackson 的結(jié)果中,原來(lái)類(lèi)中的 isSuccess 字段被序列化成 success,并且其中還包含 wanger 值。而 Gson 中只有 isSuccess 字段。

          我們可以得出結(jié)論:fastjson 和 jackson 在把對(duì)象序列化成 json 字符串的時(shí)候,是通過(guò)反射遍歷出該類(lèi)中的所有 getter 方法,得到 getHollis 和 isSuccess,然后根據(jù) JavaBeans 規(guī)則,他會(huì)認(rèn)為這是兩個(gè)屬性 hollis 和 success 的值。直接序列化成 json:

          {“wanger”:”沉默王二”,”success”:true}

          但是 Gson 并不是這么做的,他是通過(guò)反射遍歷該類(lèi)中的所有屬性,并把其值序列化成 json:

          {“isSuccess”:true}

          可以看到,由于不同的序列化工具,在進(jìn)行序列化的時(shí)候使用到的策略是不一樣的,所以,對(duì)于同一個(gè)類(lèi)的同一個(gè)對(duì)象的序列化結(jié)果可能是不同的。那么,如果我們把一個(gè)對(duì)象使用 fastjson 進(jìn)行序列化,再使用 Gson 反序列化會(huì)發(fā)生什么呢?

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

          以上代碼,輸出結(jié)果:

          Model[isSuccess=false]

          這和我們預(yù)期的結(jié)果完全相反,原因是因?yàn)?JSON 框架通過(guò)掃描所有的 getter 后發(fā)現(xiàn)有一個(gè) isSuccess 方法,然后根據(jù) JavaBeans 的規(guī)范,解析出變量名為 success,把 model 對(duì)象序列化成字符串后內(nèi)容為{"success":true}。

          根據(jù){"success":true}這個(gè) json 串,Gson 框架在通過(guò)解析后,通過(guò)反射尋找 Model 類(lèi)中的 success 屬性,但是 Model 類(lèi)中只有 isSuccess 屬性,所以,最終反序列化后的 Model 類(lèi)的對(duì)象中,isSuccess 則會(huì)使用默認(rèn)值 false。

          但是,一旦以上代碼發(fā)生在生產(chǎn)環(huán)境,這絕對(duì)是一個(gè)致命的問(wèn)題。

          所以,作為開(kāi)發(fā)者,我們應(yīng)該想辦法盡量避免這種問(wèn)題的發(fā)生。

          所以,建議大家使用 success 而不是 isSuccess 這種形式。 這樣,該類(lèi)里面的成員變量時(shí) success,getter 方法是 isSuccess,這是完全符合 JavaBeans 規(guī)范的。無(wú)論哪種序列化框架,執(zhí)行結(jié)果都一樣。就從源頭避免了這個(gè)問(wèn)題。


          沒(méi)有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧?kù)o的港灣,我是不系之舟

          推薦閱讀

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品成人午夜 | 69精品久久久久中文字幕 | 99久久精品国产99久久久久久红桃 | 久久久久性色Av免费毛片特级 | 欧美搞搞搞 |