Serializing a vector

2019-04-16 16:48发布

问题:

I'm trying to implement loading and saving for a game I'm working on.

What I want to save is:

  • A char[][] (bidimensional array/matrix)
  • An ArrayList<Entity>

Entity is a super class for Dragon, Hero and Item. All three of these types can be contained at once in the ArrayList.

So far I have this:

package logic;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public final class LoadAndSave {
    public static final transient boolean available = false;

    public static final boolean serialize(Object obj) {

        // Write to disk with FileOutputStream
        FileOutputStream saveFile;
        try {
            saveFile = new FileOutputStream("game.sav");
        } catch (FileNotFoundException e) {
            return false;
        }

        // Write object with ObjectOutputStream
        ObjectOutputStream objOut;
        try {
            objOut = new ObjectOutputStream(saveFile);
        } catch (IOException e) {
            //
            return false;
        }

        // Write object out to disk
        try {
            objOut.writeObject(obj);
        } catch (IOException e) {
            return false;
        }

        return true;
    }

    public static final Object load() {
        FileInputStream fileIn;
        try {
            fileIn = new FileInputStream("game.sav");
        } catch (FileNotFoundException e1) {
            return null;
        }

        // Read object using ObjectInputStream
        ObjectInputStream objIn;
        try {
            objIn = new ObjectInputStream(fileIn);
        } catch (IOException e) {
            return null;
        }

        // Read an object
        Object obj;
        try {
            obj = objIn.readObject();
        } catch (IOException e) {
            return null;
        } catch (ClassNotFoundException e) {
            return null;
        }

        return obj;
    }

}

I think the code is pretty self-explanatory. Now for my questions:

  1. Will this code suffice?
  2. Do I need to implement specific serialization methods for Dragon, Item and Hero?
  3. How will the serialization mechanism deal with the fact that I have an Entity vector full of types that are not Entity, but derived classes? Thanks for your time!

OK, all seems to be well, except for one the ArrayList. It is either not getting saved or loaded (null pointer exception when calling size()).

What may this be due to?

回答1:

If you want the entire structure to be serializable, then you'll need to make the parts serialiable as well. What this means in practice is that you need to make your Dragon, Hero, and Item classes implement Serializable. It's just a marker interface, so you only need to add implements Serializable. Some ides (at least eclipse, anyway) may complain that you should add a private long SerialVersionUID which may or may not optimize the serialization a bit - in any case it's not strictly necessary.

This requirement is recursive - any of their subparts that are custom or non-serializable objects have to be taken care of as well, so for example if your Item class looks like this

 public class Item implements Serializable {
    private String s;
    private MyClass c;
    ..

then you'll also need to make MyClass Serializable, any of it's instance variables, etc etc.



回答2:

I don't see any reason for specific serialization methods for Dragon, Item and Hero unless you require some very special stuff that the default serialization mechanism cannot handle. (Of course the classes need to be serializable as mentioned by Steve B)

You already have a lot of code so I suspect that you've already run some tests. Have you faced certain problems? Or how does it come that you are asking this?

Update:

I've noticed some aspects in your code which are not directly related to your question but may anyway be of interest for you:

  • Do you really mean to use Vector? Does your application make use of multithreading and serialization is required? If not you might prefer to use ArrayList or so instead.
  • The way you handle exceptions is quite strange. Perhaps you are only doing so as this is an example... You should not suppress exceptions by simply returning true or false. If you expect calling methods to be interested in exceptions you should simply add the exception to the methods signatur (throws...) and let the calling method care about it. If you feel this is not appropriate wrapping such exceptions in custom exceptions, which are more expressive in the context, might be an option. If you don't care about the exception at all wrapping it into a runtime exception is also possible. In case of success your method might simply return nothing...