序列化如何为case类工作并与java进行比较?

时间:2017-01-13 16:20:09

标签: scala serialization

当我有一个在val上有方法的case类时,究竟将序列化什么?

case class User(id: Int, name: String, age: Int) {
  val someNumber = age * 10

  def someMethod(a: Int) = ....

}

所以从上面我会想象构造函数参数和val someNumber会被序列化,而方法不会。

所以基本上方法的状态被序列化了。

scala和java序列化之间有什么重大差异吗?

2 个答案:

答案 0 :(得分:4)

Scala中的

case class序列化是我们对标准Java序列化的期望。

案例类扩展scala.Serializable,后者又扩展Any with java.io.Serializable(请参阅scala.Serializable),因此使用通常的扩展java.io.Serializable Java方法对案例类进行“标记”序列化

请注意,我们应该谈论对象序列化,而不是类序列化。序列化的是对象实例的状态,它由声明或继承的所有成员的值组成。在无体case class的情况下,如

case class User (id:Long, name:String)

所有已声明的成员都将被序列化(例如idname)。

如果case类声明了内部成员变量,那么它们也将包含在序列化形式中。

case class User (id:Long, name:String) {
  val foo = name.hashCode * id
}

serializad表单将包含(idnamefoo)。

我们可以使用@transient注释标记成员,以避免它们被序列化。

case class User (id:Long, name:String) {
  val foo = name.hashCode * id
  @transient bar = "Private Bar."
}

serializad表单将包含(idnamefoo)。

请注意,Java序列化总是涉及序列化对象图,该对象图由附加到被序列化对象的所有引用组成,因此任何成员变量引用的对象也将被序列化。

就像这种情况一样:

case class User (id:Long, name:String)
case class Product (id:Long, name:String, price: Decimal)
case class Purchase (timestamp:Long, user:User, product:Product, name:String)

所以,给定:

val beerPurchase = Purchase(now, onlineUser, leffe)

序列化beerPurchase还会涉及onlineUserleffe个对象的序列化。

请注意,可序列化类的每个成员也必须可序列化或标记为@transient。否则,尝试序列化此类将导致运行时java.io.NotSerializableException

简而言之:没有惊喜。案例类序列化是您对标准java / jvm序列化的期望。

答案 1 :(得分:0)

让我们创建一个对象并将其序列化,以便您可以轻松查看正在序列化的内容:

case class City(name: String, funActivity: String, latitude: Double)
val bengaluru = City("Bengaluru", "South Indian food", 12.97)
implicit val cityRW = upickle.default.macroRW[City]
upickle.default.write(bengaluru) // "{\"name\":\"Bengaluru\",\"funActivity\":\"South Indian food\",\"latitude\":12.97}"

封装在对象中的值正在被序列化。

您可以编写序列化程序来将数据保存在对象中。你不能序列化任何 JVM 的东西/Scala 的东西。序列化意味着将对象转换为字符串/二进制。字节数组无法存储方法之类的 JVM 内容。有关序列化 Scala 对象的详细信息,请参阅 this post