0

I intend to copy a three-dimensional array via serialization, using the following class:

public class Serializer {

    public byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(obj);
        return b.toByteArray();
    }

    public Object deserialize(byte[] bytes) throws IOException,
            ClassNotFoundException {
        ByteArrayInputStream b = new ByteArrayInputStream(bytes);
        ObjectInputStream o = new ObjectInputStream(b);
        return o.readObject();
    }
}

Then, in my main code I write this:

int array[][][] = new int[param][][];
Serializer s = new Serializer();
byte [] b = s.serialize(array);
Object arrayCopy = s.deserialize(b);

However, I do get an error message on the last line: "Unhandled exception type ClassNotFoundException"

Also, I don't know how can I convert the Object arrayCopy to an int[param][][], which is my final objective. How can I do this?

Thanks

strv7
  • 109
  • 10
  • The whole Serializer Class does not actually do, what you want. An ObjectStream reads a Java Object (e.g. a String or a List for example) not a byte array. It only reads FROM a inputstream (bytearray). – John Smith Feb 21 '13 at 11:28

1 Answers1

1

However, I do get an error message on the last line: "Unhandled exception type ClassNotFoundException"

Your deserialize method throws two checked exceptions (IOException, ClassNotFoundException), which have to be handled in calling code with a try-catch block.

Also, I don't know how can I convert the Object arrayCopy to an int[param][][], which is my final objective

You cast objects by prepending the RHS of the expression with the desired type (int[][][]), in brackets. Note that in your case, this is an unsafe cast, since you really don't know the type of object that is being returned from the deserialize method.

Combining both exception handling and casting, your main code should look something like this:

try {
    int array[][][] = new int[param][][];
    Serializer s = new Serializer();
    byte [] b = s.serialize(array);
    Object arrayCopy = (int[][][]) s.deserialize(b);
} catch(IOException ioe) {
    // ... handle this
} catch(ClassNotFoundException cnfe) {
    // ... handle this
}

Safe(er) Casting

If you wanted to avoid the unsafe casting, you could use generics to indicate the expected return type of the deserialize method. You would also need to do a validation within the method itself, that the deserialized object was actually of a desired class type. Something like this:

public class Serializer {

    public <T> byte[] serialize(T obj) throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(obj);
        return b.toByteArray();
    }

    public <T> T deserialize(Class<T> clazz, byte[] bytes) throws IOException,
            ClassNotFoundException {
        ByteArrayInputStream b = new ByteArrayInputStream(bytes);
        ObjectInputStream o = new ObjectInputStream(b);
        final Object raw = o.readObject();
        if (raw.getClass().isAssignableFrom(clazz))
            return clazz.cast(raw);
        else
            throw new IllegalArgumentException(
                    "Byte data does not represent a class of type " + clazz);
    }
}

Notice the changes to the deserialize method are:

  • Add a (method level) generic parameter T
  • Add an additional parameter (Class<T>) that represents the expected type to be returned
  • Add validation in the method to confirm that the deserialized object is in fact, an instance of the desired class
  • Add an illegal argument exception, in the case that the deserialized object is not in fact, an instance of the desired class

If you use these modifications, in your main code you should also handle IllegalArgumentException.

Perception
  • 79,279
  • 19
  • 185
  • 195