为啥类的一个不可序列化的静态字段在实例被序列化时会抛出 NotSerializableException?

Posted

技术标签:

【中文标题】为啥类的一个不可序列化的静态字段在实例被序列化时会抛出 NotSerializableException?【英文标题】:Why a static field of a class, which is not serializable, will throw NotSerializableException when an instance being serialized?为什么类的一个不可序列化的静态字段在实例被序列化时会抛出 NotSerializableException? 【发布时间】:2019-03-28 17:12:55 【问题描述】:

在scala中,我认为对象的一个​​字段在序列化时会是静态的,不会被序列化, 但如果该字段不可序列化,则会得到 NotSerializableException。 为什么 ?类似的java代码就可以了。

下面是一个简单的例子。

谢谢

Scala 代码:

package test

import java.io._
import java.util

object AStudent extends Serializable 
  var name="Jack"
  val map=new util.WeakHashMap



object SerializationDemo extends App 

  val oos = new ObjectOutputStream(new FileOutputStream("./tmp/stu"))
  println(AStudent.name)
  AStudent.name=null
  println(AStudent.name)
  oos.writeObject(AStudent)
  oos.close


Java 代码:

package test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.WeakHashMap;

public class Stu implements Serializable 
    public static String name="Jack";
    public static WeakHashMap map=new WeakHashMap();
    public static void main(String[] args) throws IOException 
        ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("./tmp/stu"));
        oos.writeObject(new Stu());
        oos.close();
    

【问题讨论】:

通常在询问异常时,您可能需要添加堆栈跟踪。除此之外,Scala 代码和 Java 代码不应该是等价的(虽然我不太了解 Scala),因为一个有实例字段,而另一个有类字段(又名静态)。 Scala 没有static 字段的概念。您可以“认为”对象A 的成员类似于Java 中的static。关键字是“认为相似”而不是实际上是静态的。对象AStudent 将是匿名类AStudent.type 的一个实例,对象AStudent 的所有成员实际上都是类AStudent.type 的成员。 【参考方案1】:

这些例子并不相同。在 Java 示例中,您正在序列化 Stu 实例,序列化将跳过 static 字段,因为它们不是实例状态的一部分。在 Scala 示例中,您正在序列化具有 map 字段的 AStudent 对象实例。由于 Scala 没有 static 概念,Java 等价物是:

public class AStudent implements Serializable 
  public Map map = new WeakHashMap();    

【讨论】:

【参考方案2】:

Scala 没有static 字段的概念。您可以“认为”对象 A 的成员类似于 Java 中的 static

关键字是“认为类似于静态”而不是实际上是 static

对象AStudent 将是匿名类AStudent.type 的一个实例,对象AStudent 的所有成员实际上都是类AStudent.type 的成员

类似于,

class AStudentType[K, V](
    var name: String ="Jack",
    val map: WeakHashMap[K, V] = new WeakHashMap()
)

val AStudent = new AStudentType[String, String]()

【讨论】:

以上是关于为啥类的一个不可序列化的静态字段在实例被序列化时会抛出 NotSerializableException?的主要内容,如果未能解决你的问题,请参考以下文章

Java序列化之排除被序列化字段(transient/静态变量)

java 序列化怎么标记为不可序列化的字段?

如何处理 Findbugs“可序列化类中的非瞬态不可序列化实例字段”?

headfirst x

静态内部类的序列化

Java.io.ObjectOutputStream.writeObject()方法实例