<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 形式定義布爾類型,下午就被勸退?

          共 5554字,需瀏覽 12分鐘

           ·

          2022-06-25 12:22

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

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

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

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

          從語義上面來講,兩種命名方式都可以講的通,并且也都沒有歧義。

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

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

          isSuccess 會有什么問題呢?小二很是不解。

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

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

          但是,布爾類型的變量 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í)候,還是會采用 isSuccess/getSuccess 作為 getter 方法名,尤其是現(xiàn)在的很多 IDE 在默認(rèn)生成 getter 的時(shí)候也是會生成 isSuccess。

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

          我們先來定義一個(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 幫我們自動生成的 isSuccess 和 setSuccess,另外一個(gè)是作者自己增加的一個(gè)符合 getter 命名規(guī)范的方法。

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

          public class BooleanMainTest {
               public static void main(String[] args) throws IOException {
                   //定一個(gè)Model類型
                   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é)果中,原來類中的 isSuccess 字段被序列化成 success,并且其中還包含 wanger 值。而 Gson 中只有 isSuccess 字段。

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

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

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

          {“isSuccess”:true}

          可以看到,由于不同的序列化工具,在進(jìn)行序列化的時(shí)候使用到的策略是不一樣的,所以,對于同一個(gè)類的同一個(gè)對象的序列化結(jié)果可能是不同的。那么,如果我們把一個(gè)對象使用 fastjson 進(jìn)行序列化,再使用 Gson 反序列化會發(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 框架通過掃描所有的 getter 后發(fā)現(xiàn)有一個(gè) isSuccess 方法,然后根據(jù) JavaBeans 的規(guī)范,解析出變量名為 success,把 model 對象序列化成字符串后內(nèi)容為{"success":true}。

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

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

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

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


          沒有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不系之舟

          JDK9為何要將String的底層實(shí)現(xiàn)由char[]改成了byte[]?


          竟然有一半的人不知道 for 與 foreach 的區(qū)別???


          消息冪等(去重)通用解決方案,RocketMQ


          關(guān)注公眾號【Java技術(shù)江湖】后回復(fù)“PDF”即可領(lǐng)取200+頁的《Java工程師面試指南》

          強(qiáng)烈推薦,幾乎涵蓋所有Java工程師必知必會的知識點(diǎn),不管是復(fù)習(xí)還是面試,都很實(shí)用。



          瀏覽 32
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  日本无码影院 | 色一情一乱一交一级A片 | 黄色性爱视频在线播放 | 一本大道久久无码精品一区二区三区 | 五月婷网 |