国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

kotlin gson反序列化默認(rèn)值失效深入講解

2024-07-21 23:03:51
字體:
供稿:網(wǎng)友

Gson反序列化原理

原理簡(jiǎn)述

gson反序列化主要分為兩個(gè)過程:

  • 根據(jù)TypeToken創(chuàng)建出對(duì)象
  • 根據(jù)json字符串解析數(shù)據(jù),對(duì)對(duì)象屬性賦值

對(duì)象的創(chuàng)建

ConstructorConstructor.get

  • 先嘗試獲取無參構(gòu)造函數(shù)
  • 失敗則嘗試List、Map等情況的構(gòu)造函數(shù)
  • 最后使用Unsafe.newInstance兜底(此兜底不會(huì)調(diào)用構(gòu)造函數(shù),導(dǎo)致所有對(duì)象初始化代碼不會(huì)調(diào)用)
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) { final Type type = typeToken.getType(); final Class<? super T> rawType = typeToken.getRawType(); // first try an instance creator @SuppressWarnings("unchecked") // types must agree final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type); if (typeCreator != null) {  return new ObjectConstructor<T>() {  @Override public T construct() {   return typeCreator.createInstance(type);  }  }; } // Next try raw type match for instance creators @SuppressWarnings("unchecked") // types must agree final InstanceCreator<T> rawTypeCreator =  (InstanceCreator<T>) instanceCreators.get(rawType); if (rawTypeCreator != null) {  return new ObjectConstructor<T>() {  @Override public T construct() {   return rawTypeCreator.createInstance(type);  }  }; } // 獲取無參構(gòu)造函數(shù) ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType); if (defaultConstructor != null) {  return defaultConstructor; } // 獲取List<T>,Map<T>等構(gòu)造函數(shù),對(duì)于List,Map的情況 ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType); if (defaultImplementation != null) {  return defaultImplementation; } // unSafe構(gòu)造出對(duì)象,不調(diào)用任何的構(gòu)造函數(shù) // finally try unsafe return newUnsafeAllocator(type, rawType); }

ConstructorConstructor.newDefaultConstructor

  • 調(diào)用Class.getDeclaredConstructor獲取無參構(gòu)造函數(shù)
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) { try {  // 獲取無參構(gòu)造函數(shù)  final Constructor<? super T> constructor = rawType.getDeclaredConstructor();  if (!constructor.isAccessible()) {  accessor.makeAccessible(constructor);  }

ConstructorConstructor.newUnsafeAllocator

  • 調(diào)用UnSafe.newInstance創(chuàng)建出對(duì)象
  • 不會(huì)調(diào)用構(gòu)造函數(shù),因此所有的初始化的代碼都不會(huì)被調(diào)用
private <T> ObjectConstructor<T> newUnsafeAllocator(  final Type type, final Class<? super T> rawType) { return new ObjectConstructor<T>() {  private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();  @SuppressWarnings("unchecked")  @Override public T construct() {  try {  //    Object newInstance = unsafeAllocator.newInstance(rawType);   return (T) newInstance;  } catch (Exception e) {   throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "    + "Registering an InstanceCreator with Gson for this type may fix this problem."), e);  }  } }; }

結(jié)論

  • Gson反序列要工作正常,使結(jié)果符合預(yù)期的話,要求類必須有一個(gè)無參構(gòu)造函數(shù)

kotlin構(gòu)造函數(shù)默認(rèn)參數(shù)和無參構(gòu)造函數(shù)的關(guān)系

參數(shù)里面存在沒有默認(rèn)值的情況

kotlin代碼

  • id沒有默認(rèn)值
class User(val id: Int, val name: String = "sss") { init {  println("init") }}

反編譯的Java代碼

  • 包含兩個(gè)構(gòu)造函數(shù),一個(gè)是我們聲明的全參數(shù)構(gòu)造函數(shù),另一個(gè)是kotlin生成的輔助構(gòu)造函數(shù)
  • 不包含無參構(gòu)造函數(shù)
public final class User { private final int id; @NotNull private final String name;  public User(int id, @NotNull String name) {  Intrinsics.checkParameterIsNotNull(name, "name");  super();  this.id = id;  this.name = name;  String var3 = "init";  System.out.println(var3); } // $FF: synthetic method public User(int var1, String var2, int var3, DefaultConstructorMarker var4) {  if ((var3 & 2) != 0) {   var2 = "";  }  this(var1, var2); }}

gson反序列化輸出

代碼:

 @Test fun testJson() {  val user = Gson().fromJson("{}", User::class.java)  print(user.name) }

輸出:不符合預(yù)期(我們聲明的非空的name實(shí)際結(jié)果是null)

null
Process finished with exit code 0

參數(shù)都包含默認(rèn)參數(shù)的情況

kotlin代碼

class User(val id: Int=1, val name: String = "sss") { init {  println("init") }}

反編譯Java代碼

  • 除了上面的兩個(gè)構(gòu)造函數(shù),多了一個(gè)無參構(gòu)造函數(shù)(從邏輯上講,這個(gè)也符合預(yù)期)
public final class User { private final int id; @NotNull private final String name; public User(int id, @NotNull String name) {  Intrinsics.checkParameterIsNotNull(name, "name");  super();  this.id = id;  this.name = name;  String var3 = "init";  System.out.println(var3); } // $FF: synthetic method public User(int var1, String var2, int var3, DefaultConstructorMarker var4) {  if ((var3 & 1) != 0) {   var1 = 1;  }  if ((var3 & 2) != 0) {   var2 = "";  }  this(var1, var2); } // 無參構(gòu)造函數(shù) public User() {  this(0, (String)null, 3, (DefaultConstructorMarker)null); }}

gson反序列化輸出

代碼:

 @Test fun testJson() {  val user = Gson().fromJson("{}", User::class.java)  print(user.name) }

輸出:符合預(yù)期

init
sss
Process finished with exit code 0

Best Practice

Practice1

  • 屬性聲明在構(gòu)造函數(shù),所有參數(shù)都帶默認(rèn)值
  • 不確定的參數(shù)聲明為可空
class User(val id: Int=1 , val name: String = "sss") { init {  println("init") }}

Practice2

回歸到Java的寫法即可

class User { val id: Int = 1 val name: String = "sss" init {  println("init") }}

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到kotlin教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 遵义县| 余姚市| 天津市| 衢州市| 疏勒县| 克拉玛依市| 浦城县| 靖西县| 故城县| 张家口市| 油尖旺区| 遵义县| 光山县| 翼城县| 安宁市| 荆州市| 兴业县| 五大连池市| 溧阳市| 昌邑市| 玛多县| 新巴尔虎左旗| 晋州市| 龙门县| 张北县| 来安县| 吉首市| 丁青县| 延安市| 同心县| 昌平区| 佳木斯市| 广安市| 民乐县| 嘉义县| 盐池县| 枣强县| 平湖市| 十堰市| 贵德县| 元江|