scala.Enumerationの直列化
2.7.2 RC2で直列化できるようになったので、試してみた。
import java.io._
object MyEnum extends test.Enumeration {
val One = Value("One")
val Two = Value("Two")
}
object Test {
def main(args: Array[String]) {
val baos = new ByteArrayOutputStream()
val oos = new ObjectOutputStream(baos)
oos.writeObject(MyEnum.One)
oos.close()
val data = baos.toByteArray()
println("size = " + data.length)
val ois = new ObjectInputStream(new ByteArrayInputStream(data))
val o = ois.readObject()
println(MyEnum.One eq o)
}
}
だと、falseと表示されるし、サイズが、1041バイトもあった。そりゃエンクロージングクラスのインスタンスまで直列化しているからなぁ。Enumerationのソースを見ると、
protected class Val(i: Int, name: String) extends Value {
...
private def readResolve(): AnyRef =
if (values ne null) values(i)
else this
}
なるほど。valuesがnullだから、新しくインスタンス生成されてしまうわけだ。でもまぁ、Scalaの場合、==は、equals呼び出しになるから、直列化復元で別のオブジェクトになってしまっても、値が一緒ならいいのかもしれない。メモリ節約にこだわるなら、
object MyEnum extends Enumeration {
protected class Val(name: String) extends super.Val {
private def readResolve(): AnyRef = MyEnum.apply(id)
}
val One = new Val("One")
val Two = new Val("Two")
}
なら、うまくいった。う〜む、しかしEnum一個直列化して1k byteでは、ちょっとなぁ。エンクロージングクラスの名前を取る方法があれば、なんとかできそうな気がするけど、この手のsyntheticフィールド名は実装依存だし、APIにも取得用のメソッドは存在しない。無理だろうか。








