Gson反序列化工作很奇怪

Gson deserialization works strangly

今天我发现了一些奇怪的Gson行为。假设我们有以下简单的 JSON

{
    "a": {
        "foo": 123
    }
}

用对应的类表示


class A(val foo: Int)

class B(val a: A) {
    val foo = a.foo
}

但是,请注意,BAfoo 有一个 'shortcut'。问题是在 GSON 反序列化过程中,这个字段没有被初始化。意思是 assertEquals(123, b.foo) 失败。

首先我查看了生成的字节码,反编译了它,但看起来不错:


 public static final class A {
      private final int foo;

      public final int getFoo() {
         return this.foo;
      }

      public A(int foo) {
         this.foo = foo;
      }
   }

public static final class B {
      private final int foo;
      @NotNull
      private final SubscriptionChangeTest.A a;

      public final int getFoo() {
         return this.foo;
      }

      @NotNull
      public final SubscriptionChangeTest.A getA() {
         return this.a;
      }

      public B(@NotNull SubscriptionChangeTest.A a) {
         Intrinsics.checkNotNullParameter(a, "a");
         super();
         this.a = a;
         this.foo = this.a.getFoo();
      }
   }

我看到的唯一原因是 GSON 不调用构造函数,而是在创建对象后使用反射填充那些 final 字段。如果您愿意分享您的想法,我将不胜感激。提前致谢。

P.S 他们的问题不是如何解决,很简单(将 B.foo 更改为 getter 属性 ),而是为什么它会这样工作

事实证明,Gson 确实不调用构造函数,而是使用 sun.misc.unsafe 创建对象。