麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > 綜合 > 正文

kotlin gson反序列化默認值失效深入講解

2024-07-21 23:03:51
字體:
來源:轉載
供稿:網友

Gson反序列化原理

原理簡述

gson反序列化主要分為兩個過程:

  • 根據TypeToken創建出對象
  • 根據json字符串解析數據,對對象屬性賦值

對象的創建

ConstructorConstructor.get

  • 先嘗試獲取無參構造函數
  • 失敗則嘗試List、Map等情況的構造函數
  • 最后使用Unsafe.newInstance兜底(此兜底不會調用構造函數,導致所有對象初始化代碼不會調用)
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);  }  }; } // 獲取無參構造函數 ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType); if (defaultConstructor != null) {  return defaultConstructor; } // 獲取List<T>,Map<T>等構造函數,對于List,Map的情況 ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType); if (defaultImplementation != null) {  return defaultImplementation; } // unSafe構造出對象,不調用任何的構造函數 // finally try unsafe return newUnsafeAllocator(type, rawType); }

ConstructorConstructor.newDefaultConstructor

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

ConstructorConstructor.newUnsafeAllocator

  • 調用UnSafe.newInstance創建出對象
  • 不會調用構造函數,因此所有的初始化的代碼都不會被調用
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);  }  } }; }

結論

  • Gson反序列要工作正常,使結果符合預期的話,要求類必須有一個無參構造函數

kotlin構造函數默認參數和無參構造函數的關系

參數里面存在沒有默認值的情況

kotlin代碼

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

反編譯的Java代碼

  • 包含兩個構造函數,一個是我們聲明的全參數構造函數,另一個是kotlin生成的輔助構造函數
  • 不包含無參構造函數
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) }

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

null
Process finished with exit code 0

參數都包含默認參數的情況

kotlin代碼

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

反編譯Java代碼

  • 除了上面的兩個構造函數,多了一個無參構造函數(從邏輯上講,這個也符合預期)
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); } // 無參構造函數 public User() {  this(0, (String)null, 3, (DefaultConstructorMarker)null); }}

gson反序列化輸出

代碼:

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

輸出:符合預期

init
sss
Process finished with exit code 0

Best Practice

Practice1

  • 屬性聲明在構造函數,所有參數都帶默認值
  • 不確定的參數聲明為可空
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") }}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 深夜免费视频 | 亚洲精中文字幕二区三区 | 免费在线观看毛片视频 | 国产精品视频六区 | 美女毛片儿 | 欧美日本国产精品 | 久久久久久久久久久一区 | 久国产精品视频 | 一级全毛片 | 综合图区亚洲 | 久久久久av69精品 | 黄色大片高清 | 久久久久久亚洲综合影院红桃 | 羞羞视频一区 | 毛片在线免费播放 | 欧美一级片网站 | 精品一区二区三区免费看 | 免费国产网站 | 黄色7777 | chinesexxxx刘婷hd 国产91在线播放九色 | 最新se94se在线欧美 | 国产福利视频 | 久久久久久久一区二区三区 | 免费在线观看成年人视频 | 精品一区二区6 | 国产精品免费一区二区 | 日韩黄色片免费看 | 黄色网址在线免费播放 | 国产 一区 | 久久中文一区 | 亚洲国产网站 | 国产免费一区视频 | 手机av免费电影 | 黄色片免费在线 | 久草视频手机在线观看 | 精品久久久久久久久久久久久 | 国产成人高清成人av片在线看 | 亚洲aⅴ免费在线观看 | 日韩免费黄色 | www国产网站 | 亚洲一区在线观看视频 |