I am working on building a music.player and have my music-library stored in a HashMap. The User shall be able to add and delete songs. I want to save this HashMap for when the program is beeing restartet. However did I encounter this warning:
Exception in thread "main" java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: musicplayer.Song
Research showed I have to implement the Serializable Interface in my Song class. Which I did, but with still this warning. My Song class:
package musicplayer;
//Song-Klasse, speichert alle Attribute und Methoden eines Songs. Funktioniert soweit
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
public class Song implements Serializable {
private static final long serialVersionUID = 4390482518182625971L;
//Attribute
File file;
Clip clip;
String string;
//...
The MusicDaten - Class
package musicplayer;
public class MusicDaten implements Serializable {
private static Map<String,Song> all; //= new HashMap<String,Song>();
private File file = new File("C://Users//ThinkPad T450s//git//testproject//musicplayer//SongInfo.ser");
// ...
public MusicDaten() throws ClassNotFoundException, IOException {
this.setSavedSongs();
}
public void setSavedSongs() throws IOException, ClassNotFoundException { //initialisziert HashMap mit den gespeicherten Songs
FileInputStream fileIn = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fileIn);
all = (HashMap<String,Song>) in.readObject();
in.close();
fileIn.close();
}
public void save() throws IOException { //Speicher HashMap
FileOutputStream fileOut = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(all);
out.close();
fileOut.close();
System.out.println("Songinfo saved");
}
Thank you for the help. (I have edited this question since before it wasn't quite clear)
Implementing
Serializableis not sufficient.If you attempt to serialize an object, all its non-transient attributes are serialized, too. If any of those attributes is not
Serializable, it will not work.In your case,
Songcontains an attribute of typeFileandFileis not serializable. WithClip, you have the same problem.In order to get around this, you can do custom serialization.
Looking at the docs of
Serializable, you can find this:This means that you can create the methods
writeObjectandreadObjectwhere you specify how to (de)serialize the object.If you want to keep the default (de)serialization of the attributes supporting serialization, you can mark all fields not supporting serialization
transientand callout.defaultWriteObject/in.defaultReadObjectin thewriteObject/readObjectmethods.Marking an attribute
transientmeans that serialization ignores it. You can then use your custom logic.Note that serialization comes with some problems and you might not want to use it.
On one hand, it can lead to serious denial of service and even remote code execution vulnerabilities if you deserialize untrusted data. This is also noted in the docs of
Serializable:Another problem of serialization is that it binds your application to a fixed format and makes it difficult to be compatible with old serialized data when update your application if you didn't carefully think it through when initially creating it.
For more information about this, you may want to consider reading the book
Effective Java.