简体   繁体   中英

Java serialization of a value in a Scala singleton object

I have Scala singleton objects Works and Broken that look very similar:

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
  }
}

What I'd like to understand is why is Works.factory serializable but Broken.factory isn't?

To serialise a class all members must also be serialisable. However consider -Xprint:jvm output of the anonymous new Serializable in 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>();
      ()
    }
  }

In particular note the member

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

The class of instance referenced by $outer is A , however trait A has not been declared as Serializable . Therefore serialisation of anonymous class referenced by Broken.factory fails.

On the other hand, consider -Xprint:jvm output of the anonymous new Serializable in 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>();
      ()
    }
  }

Notice there is no member (similar to $outer ) that is not Serializable . Therefore serialisation of anonymous class referenced by Works.factory succeeds.

The fix is to make trait A serialisiable like so

trait A extends Serializable { ... }

however Java Object Serialization Specification warns

Serialization of inner classes (ie, nested classes that are not static member classes), including local and anonymous classes, is strongly discouraged for several reasons. Because inner classes declared in non-static contexts contain implicit non-transient references to enclosing class instances, serializing such an inner class instance will result in serialization of its associated outer class instance as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM