Для сериализации класса все члены также должны быть сериализуемыми. Однако рассмотрим -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 контекстах, содержат неявные непереходные ссылки на включающие экземпляры классов, сериализация такого внутреннего экземпляра класса также приведет к сериализации его соответствующего экземпляра внешнего класса.