为什么我在尝试序列化对象时会收到NotSerializable Exception

发布于 2025-01-22 13:40:51 字数 1879 浏览 1 评论 0 原文

我有以下课程:

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();
}

我不知道为什么会发生,我会搜索并找到一些答案,告诉您要实现实现序列化。我做到了,但我仍收到 notSerializableException

为什么会发生?我该怎么办?

错误消息

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)

I have the following class:

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

    // constructor etc.
}

in another class, I tried to save GameWorld, but received not serializable exception:

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();
}

I don't know why it's happen, I search on SO and find some answers told you to implement Serializable. I did it, and I'm still receiving NotSerializableException.

Why is that to happen? What can I do to fix it?

Error-message:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烂人 2025-01-29 13:40:51

整个对象图需要序列化,如果至少一个字段未实现序列化接口,则在尝试序列化此类实例时会得到异常。

引用来自

遍历图时,可能会遇到不支持可序列化接口的对象。在这种情况下,将抛出 notSerializableException ,并将标识非序列化对象的类。

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

您可以使用这些类型遇到麻烦

  • 对象不实现 serializable ,因此 object 类型字段是在班级中不允许序列化。
  • 可选以及 optionalInt optionallong optianaldouble 不可序列化,因为将可选类型引入了有限的机制
    对于返回类型,而不是打算用作字段。
  • 您的自定义类型用作可序列化类的字段必须是可序列化的。 Tiles 类必须实现序列化,如果 Tiles内部有一些自定义字段类型,它们也必须序列化。

如果您不希望特定字段被序列化,则可以将其标记为瞬态。在序列化过程中忽略了瞬态字段以及静态字段。

因此,如果您将字段 tileGroup loadingtiles transient ,那么 tiles class class becals n demboce n n demboce n n the Compand n n the Code> both in Code> the code>实现序列化,因为这些属性将从序列化版本中排除。作为避难所后的一致性,它们将被初始化为 null

通常,序列化将用于临时数据存储或传输数据。为了确保从内存中检索的对象与 .class 文件兼容,您有一个很好的做法来定义静态最终long serialversionuid 字段,该字段表示当前版本班级。

序列化运行时与每个可序列化类A
版本号,称为serialversionuid,在此期间使用
进行验证以验证序列化的发件人和接收器
对象已加载与该对象兼容的对象的类
尊重序列化。如果接收器已为
对象具有不同的序列化元素。
相应的发送者的类,然后进行挑战将导致
无效的Classexception。可序列化的类可以声明自己的
通过声明一个名称的字段,明确表示
必须是静态,最终且类型长的“ serialversionuid”:

Any-Access-Modifier 静态最终long serialversionuid = 42L;

,您还应该意识到,序列化具有一些严重的绘图(<<<<<<<< em>查看上面提供的链接)。

sidenote :class-names通常是单数名词喜欢 student 雇员,<代码>图块,因为它们的实例旨在表示一个对象。

The whole object graph needs to be serializable, if at least one of the fields doesn't implement Serializable interface you'll get an exception while attempting to serialize the instance of this class.

Quote from the 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.

Primitive types and most of the data-types built-in in the JDK are serializable.

You can run into troubles only with these types:

  • Object doesn't implement Serializable, hence Object type fields are not allowed in the class that is meant to be serializable.
  • Optional as well as OptionalInt, OptionalLong and OptianalDouble aren't serializable because optional types were introduced as limited mechanism
    for return types and not intended to be used as fields.
  • Your custom types used as a field of a serializable class has to be serializable. Tiles class has to implement Serializable and if there are some custom field types inside the Tiles, they must be serializable as well.

If you don't want a particular field to be serialized, you can mark it as transient. Transient fields as well as static fields are ignored during the serialization process.

So if you would make the fields tileGroup and loadingTiles to be transient, then Tiles class will not be required to implement Serializable because these attributes will be excluded from the serialized version. And as a consiquence after deserialization they will be initialized to null.

In general, serialization is meant to be used for temporary data-storage or transferring the data. To ensure that an object retrieved from memory is compatible with the .class file that you have it a good practice to define static final long serialVersionUID field, which denotes the current version of the 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;

Also, you should be aware that serialization has some serious draw-backs (take a look at the link provided above).

Sidenote: class-names are usually singular nouns like Student, Employee, Tile because their instances are meant to represent a single object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文