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)
CodePudding user response:
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 implementSerializable
, henceObject
type fields are not allowed in the class that is meant to be serializable.Optional
as well asOptionalInt
,OptionalLong
andOptianalDouble
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 implementSerializable
and if there are some custom field types inside theTiles
, 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
field 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.