Java сериализация значения в одноэлементном объекте Scala - PullRequest
2 голосов
/ 09 января 2020

У меня есть Scala одноэлементных объектов Works и Broken, которые очень похожи:

object Works {
  def i = ???
  val factory = new Serializable {
    def get = i
  }
}

object Broken extends A

trait A {
  def i = ???
  val factory = new Serializable {
    def get = i
  }
}

Я хотел бы понять, почему Works.factory сериализуем, но Broken.factory нет «т

1 Ответ

2 голосов
/ 09 января 2020

Для сериализации класса все члены также должны быть сериализуемыми. Однако рассмотрим -Xprint:jvm вывод анонимного new Serializable в trait A

  final class anon$1 extends Object with java.io.Serializable {
    def get(): Nothing = anon$1.this.$outer.i();
    <synthetic> <paramaccessor> <artifact> private[this] val $outer: $line58.iw$A = _;
    def <init>($outer: $line58.iw$A): <$anon: Object> = {
      if ($outer.eq(null))
        throw null
      else
        anon$1.this.$outer = $outer;
      anon$1.super.<init>();
      ()
    }
  }

В частности, обратите внимание на член

<synthetic> <paramaccessor> <artifact> private[this] val $outer: $line58.iw$A = _;

Класс экземпляра, на который ссылается $outer, равен A, однако trait A имеет , а не был объявлен как Serializable. Поэтому сериализация анонимного класса, на который ссылается Broken.factory, завершается неудачей.

С другой стороны, рассмотрим -Xprint:jvm вывод анонимного new Serializable в object Works

  final class anon$1 extends Object with java.io.Serializable {
    def get(): Nothing = iw$Works.this.i();
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      ()
    }
  }

Обратите внимание, что есть нет члена (похожего на $outer), который не является Serializable. Поэтому сериализация анонимного класса, на который ссылается Works.factory, завершается успешно.

Исправление заключается в том, чтобы сделать черту A serialisiable такой же, как и так

trait A extends Serializable { ... }

однако Java Спецификация сериализации объекта warns

Сериализация внутренних классов (т. Е. Вложенных классов, не являющихся классами-членами c), включая локальные и анонимные классы, настоятельно не рекомендуется по нескольким причинам. Поскольку внутренние классы, объявленные в нестатических c контекстах, содержат неявные непереходные ссылки на включающие экземпляры классов, сериализация такого внутреннего экземпляра класса также приведет к сериализации его соответствующего экземпляра внешнего класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...