java - 为什么我在尝试序列化对象时收到 NotSerializedException

标签 java serialization io objectoutputstream notserializableexception

我有以下类(class):

public class GameWorld implements Serializable {
    int sumu_dist = 30;
    public List<Tiles> tileGroup = new ArrayList<>();
    public List<Tiles> loadingTiles = new ArrayList<>();

    // constructor etc.
}

在另一个类中,我尝试保存GameWorld,但收到了不可序列化的异常:

public class game {

    static GameWorld GameWorldObj = new GameWorld();

    String FileName = "WorldData.bin";

void Save(){
    try {
        FileOutputStream FOS = new FileOutputStream(FileName);
        ObjectOutputStream OOS = new ObjectOutputStream(FOS);
        if (gameworld_obj instanceof Serializable){
            OOS.writeObject(GameWorldObj); // java.io.NotSerializableException
        }
        System.out.printf("SAVED: %s \n", OOS);
        OOS.close();
    } catch (IOException exception){
        System.err.println(String.valueOf(exception));
    } 
    
}   

public static void main(String[] args) {
    new game().Save();
}

我不知道为什么会发生这种情况,我搜索了SO并找到了一些答案告诉你实现Serialized。我做到了,但仍然收到 NotSerializedException

为什么会发生这种情况?我可以做什么来修复它?

错误消息:

java.io.NotSerializableException: source.library.level.Tiles
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1197)
    at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1582)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1539)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1448)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1191)
    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
    at source.library.level.game.Save(game.java:33)
    at source.library.level.game.main(game.java:47)

最佳答案

整个对象图需要可序列化,如果至少有一个字段没有实现 Serialized 接口(interface),那么在尝试序列化此类的实例时将会出现异常。

引自 documentation :

When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.

基本类型和 JDK 中内置的大多数数据类型都是可序列化的。

可能会遇到以下类型的麻烦:

  • Object 未实现 Serializable,因此在可序列化的类中不允许使用 Object 类型字段。<
  • Optional 以及 OptionalIntOptionalLongOptianalDouble 不可序列化,因为可选类型被​​引入为有限机制 用于返回类型并且不打算用作字段。
  • 用作可序列化类的字段的自定义类型必须是可序列化的。 Tiles 类必须实现 Serializable,并且如果 Tiles 中有一些自定义字段类型,它们也必须是可序列化的。

如果您不希望序列化特定字段,可以将其标记为transient。在序列化过程中, transient 字段和静态字段都会被忽略。

因此,如果您将 tileGrouploadingTiles 字段设为 transient,则 Tiles 类将不会需要实现Serialized,因为这些属性将从序列化版本中排除。作为反序列化后的结果,它们将被初始化为 null

一般来说,序列化用于临时数据存储或传输数据。为了确保从内存中检索的对象与 .class 文件兼容,最好定义 static Final long serialVersionUID 字段,该字段表示当前版本类(class)。

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

此外,您应该意识到序列化有一些严重的缺点(查看上面提供的链接)。

旁注:类名通常是单数名词,例如StudentEmployeeTile 因为它们的实例代表单个对象。

关于java - 为什么我在尝试序列化对象时收到 NotSerializedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71915037/

相关文章:

java - Jackson UpperCamelCase - 不将单个单词属性大写

java - 扫描仪在使用 next() 或 nextFoo() 后跳过 nextLine()?

java - Java中的基本输入和输出

java - 带有部分的 Recyclerview,但每个部分仅带有页脚

java - 什么加载了 Java 系统类加载器?

java - Spring MVC。 POST 表单未绑定(bind)

java - 从 excel XSSFCell cell = row.getCell(j) 读取时获取空指针异常 java;

c++ - 如何抑制 boost serialization::archive 中的额外信息?

php - JMS 反序列化对象中的 ArrayCollection

io - 如何在 C 中调用 execvp 后将错误消息传递给文件