我有以下类(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
以及OptionalInt
、OptionalLong
和OptianalDouble
不可序列化,因为可选类型被引入为有限机制 用于返回类型并且不打算用作字段。- 用作可序列化类的字段的自定义类型必须是可序列化的。
Tiles
类必须实现Serializable
,并且如果Tiles
中有一些自定义字段类型,它们也必须是可序列化的。
如果您不希望序列化特定字段,可以将其标记为transient
。在序列化过程中, transient 字段和静态
字段都会被忽略。
因此,如果您将 tileGroup
和 loadingTiles
字段设为 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;
此外,您应该意识到序列化有一些严重的缺点(查看上面提供的链接)。
旁注:类名通常是单数名词,例如Student
、Employee
、Tile
因为它们的实例代表单个对象。
关于java - 为什么我在尝试序列化对象时收到 NotSerializedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71915037/