为什么我在尝试序列化对象时收到 NotSerializableException
Why I receive NotSerializableException while attempting to Serialize an Object
我有以下 class:
public class GameWorld implements Serializable {
int sumu_dist = 30;
public List<Tiles> tileGroup = new ArrayList<>();
public List<Tiles> loadingTiles = new ArrayList<>();
// constructor etc.
}
在另一个 class 中,我试图保存 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 上搜索并找到了一些告诉你实施的答案 Serializable
。我做到了,我仍然收到 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)
整个对象图需要是可序列化的,如果至少有一个字段没有实现 Serializable
接口,您将在尝试序列化此 class 的实例时遇到异常.
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 中的大多数 data-types built-in 都是可序列化的。
您可能 运行 遇到麻烦 只有 这些类型:
Object
没有实现 Serializable
,因此 Object
类型字段不允许出现在 class 中,这意味着可序列化。
Optional
以及 OptionalInt
、OptionalLong
和 OptianalDouble
不可序列化,因为可选类型是作为有限机制引入的
对于 return 类型 并且不打算用作字段。
- 用作可序列化字段的自定义类型 class 必须是可序列化的。
Tiles
class 必须实现 Serializable
并且如果 Tiles
中有一些自定义字段类型,它们也必须是可序列化的。
如果您不希望某个特定字段被序列化,您可以将其标记为transient
。瞬态字段以及 static
字段在序列化过程中被忽略。
因此,如果您将字段 tileGroup
和 loadingTiles
设为 transient
,则 Tiles
class 将不需要实现 Serializable
因为这些属性将从序列化版本中排除。作为反序列化后的结果,它们将被初始化为 null
.
一般来说,序列化是用来临时data-storage或者传输数据的。为确保从内存中检索到的对象与 .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;
此外,您应该知道序列化有一些严重的draw-backs(看看上面提供的link)。
旁注:class-names通常是单数名词,例如Student
、Employee
、Tile
,因为它们的实例旨在表示单个对象。
我有以下 class:
public class GameWorld implements Serializable {
int sumu_dist = 30;
public List<Tiles> tileGroup = new ArrayList<>();
public List<Tiles> loadingTiles = new ArrayList<>();
// constructor etc.
}
在另一个 class 中,我试图保存 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 上搜索并找到了一些告诉你实施的答案 Serializable
。我做到了,我仍然收到 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)
整个对象图需要是可序列化的,如果至少有一个字段没有实现 Serializable
接口,您将在尝试序列化此 class 的实例时遇到异常.
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 中的大多数 data-types built-in 都是可序列化的。
您可能 运行 遇到麻烦 只有 这些类型:
Object
没有实现Serializable
,因此Object
类型字段不允许出现在 class 中,这意味着可序列化。Optional
以及OptionalInt
、OptionalLong
和OptianalDouble
不可序列化,因为可选类型是作为有限机制引入的 对于 return 类型 并且不打算用作字段。- 用作可序列化字段的自定义类型 class 必须是可序列化的。
Tiles
class 必须实现Serializable
并且如果Tiles
中有一些自定义字段类型,它们也必须是可序列化的。
如果您不希望某个特定字段被序列化,您可以将其标记为transient
。瞬态字段以及 static
字段在序列化过程中被忽略。
因此,如果您将字段 tileGroup
和 loadingTiles
设为 transient
,则 Tiles
class 将不需要实现 Serializable
因为这些属性将从序列化版本中排除。作为反序列化后的结果,它们将被初始化为 null
.
一般来说,序列化是用来临时data-storage或者传输数据的。为确保从内存中检索到的对象与 .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;
此外,您应该知道序列化有一些严重的draw-backs(看看上面提供的link)。
旁注:class-names通常是单数名词,例如Student
、Employee
、Tile
,因为它们的实例旨在表示单个对象。