为什么POJO中变量不能用is开头
一、前言
在阿里編碼規(guī)約中,有一個(gè)約定如下
【強(qiáng)制】POJO 類中的任何布爾類型的變量,都不要加 is 前綴,否則部分框架解析會(huì)引起序列 化錯(cuò)誤。
但為什么類中的field不能用is開頭呢?本文將從問題演示、框架源碼(本文使用的Jackson)兩個(gè)方面來進(jìn)行闡述。
二、問題演示
本文使用的Jackson,需要引入相關(guān)依賴,maven依賴如下,gradle配置請(qǐng)自行尋找。
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.11.0</version> </dependency>首先寫一個(gè)簡單的POJO,在這個(gè)POJO中,有三個(gè)屬性,分別是isSuccess/code/msg,并自動(dòng)生成了對(duì)應(yīng)的get方法,這里要注意,isSuccess屬性對(duì)應(yīng)的get方法名也是isSuccess()。代碼如下
public class Pojo {private boolean isSuccess;private int code;private String msg;private Pojo(boolean success, int code, String msg) {this.isSuccess = success;this.code = code;this.msg = msg;}public static Pojo buildSuccess() {return new Pojo(true, 2000, "success");}public boolean isSuccess() {return isSuccess;}public int getCode() {return code;}public String getMsg() {return msg;}@Overridepublic String toString() {return "Pojo{" +"isSuccess=" + isSuccess +", code=" + code +", msg='" + msg + '\'' +'}';} }然后再寫一個(gè)類,在這個(gè)類中測試對(duì)POJO的序列化。在主函數(shù)中,會(huì)先創(chuàng)建一個(gè)POJO,然后將其打印,接著會(huì)使用Jackson中的ObjectMapper將對(duì)象序列化成Json字符串并打印。
public class Main {public static void main(String[] args) {ObjectMapper mapper = new ObjectMapper();Pojo pojo = Pojo.buildSuccess();System.out.println("raw pojo1: " + pojo.toString());try {System.out.println("serialize pojo1: " + mapper.writeValueAsString(pojo));} catch (IOException e) {System.out.println(e);}} }執(zhí)行main()方法后,得到運(yùn)行結(jié)果如下圖:
可以發(fā)現(xiàn),使用ObjectMapper對(duì)象將POJO序列化成String后,輸出的變量名是success,而原有POJO中的變量isSuccess丟失。將該Json串反序列化成對(duì)象,會(huì)出現(xiàn)問題。
三、源碼解析
// TODO 待源碼大致讀懂后再補(bǔ)充
源碼看不太懂,只講解一下核心的流程。由于Jackson擴(kuò)展性很好,對(duì)各種復(fù)雜情況都進(jìn)行了處理,這里只講解最普通的分支流程。
主要方法是POJOPropertiesCollector#collectAll()
protected void collectAll(){LinkedHashMap<String, POJOPropertyBuilder> props = new LinkedHashMap<String, POJOPropertyBuilder>();// First: gather basic data_addFields(props); // note: populates _fieldRenameMappings_addMethods(props);// 25-Jan-2016, tatu: Avoid introspecting (constructor-)creators for non-static// inner classes, see [databind#1502]if (!_classDef.isNonStaticInnerClass()) {_addCreators(props);}// Remove ignored properties, first; this MUST precede annotation merging// since logic relies on knowing exactly which accessor has which annotation_removeUnwantedProperties(props);// and then remove unneeded accessors (wrt read-only, read-write)_removeUnwantedAccessor(props);// Rename remaining properties_renameProperties(props);// and now add injectables, but taking care to avoid overlapping ones// via creator and regular properties_addInjectables(props);// then merge annotations, to simplify further processing// 26-Sep-2017, tatu: Before 2.9.2 was done earlier but that prevented some of// annotations from getting properly mergedfor (POJOPropertyBuilder property : props.values()) {property.mergeAnnotations(_forSerialization);}// And use custom naming strategy, if applicable...PropertyNamingStrategy naming = _findNamingStrategy();if (naming != null) {_renameUsing(props, naming);}// Sort by visibility (explicit over implicit); drop all but first of member// type (getter, setter etc) if there is visibility differencefor (POJOPropertyBuilder property : props.values()) {property.trimByVisibility();}// and, if required, apply wrapper name: note, MUST be done after// annotations are merged.if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) {_renameWithWrappers(props);}// well, almost last: there's still ordering..._sortProperties(props);_properties = props;_collected = true;}四、結(jié)論
通過上述論證,我們不難發(fā)現(xiàn),類中的屬性用is開頭會(huì)導(dǎo)致對(duì)象序列化后產(chǎn)生意想不到的結(jié)果。所以在平時(shí)編碼的過程中,我們不能在類變量中用is開頭如: “isSuccess”,這樣容易造成程序錯(cuò)誤。
如果情況特殊,也不必墨守成規(guī),只是需要預(yù)先判斷可能產(chǎn)生的影響、影響范圍、能否監(jiān)控等問題。更特殊的情況,你可以將變量名定義為isIsSuccess,或者將isSuccess定義為public。
總結(jié)
以上是生活随笔為你收集整理的为什么POJO中变量不能用is开头的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Debug pip: Could not
- 下一篇: 时间序列:简易prophet