The readObject()
method of the ObjectInputStream
returns Object and that needs to be casted
to appropriate type
. what if I serialize
an array of String
, do I get array of Objects
or Array of Strings
. I tried this below. String[] arr = (String[]) objArr;
fail in general case.
but after Serialization
, when I cast the Object
returned from readObject()
to String[]
, I do not get any Exception
. so what is that returning?
the method signature of readObject() is
public final Object readObject() throws IOException, ClassNotFoundException
which indicates it returns the Object.
why casting it to String[]
works here, but in a more general case (as shown below) it fails.
public class UpcastDownCast {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//the below three lines give runtime Exception
Object[] objArr = {new String("hello"), new String("world")};
String[] arr = (String[]) objArr;
System.out.println(Arrays.toString(arr));
String[] arrV={new String("Car"), new String("Bike")};
FileOutputStream of= new FileOutputStream("file.ser");
ObjectOutputStream oos=new ObjectOutputStream(of);
oos.writeObject(arrV);
FileInputStream fi = new FileInputStream("file.ser");
ObjectInputStream ois= new ObjectInputStream(fi);
String[] t2= (String[]) ois.readObject();
System.out.println("after "+ Arrays.toString(t2));
}
}
Array variance allows you to treat a String[]
as an Object[]
with no problems, and you can then cast back with no problems:
Object[] x = new String[] { "x", "y", "z" };
System.out.println(x.getClass()); // Prints class [Ljava.lang.String;
String[] y = (String[]) x; // No exception
This corresponds with your serialization case - serialization is merely preserving the type of the array (as I'd expect it to - it would be very broken otherwise). Serialization is really a red herring here - it's easy to demonstrate the same issue without using serialization at all.
The problem with the cast at the start of your code is due to your array initialization, which is creating an Object[]
instance, not a String[]
instance:
Object[] x = { "x", "y", "z" };
System.out.println(x.getClass()); // Prints class [Ljava.lang.Object;
String[] y = (String[]) x; // ClassCastException
That first line is equivalent to:
Object[] x = new Object[] { "x", "y", "z" };
The type of array to create is inferred not from the elements of the array, but from the type of the variable which is being declared. (Unfortunately that's not terribly clearly specified in the JLS, as far as I can tell... but it's definitely the way it works.)
If you change the declaration of the variable your using for serialization to:
Object[] arrV={new String("Car"), new String("Bike")};
... then you'll see the same exception when you cast the deserialized result.
(Also note that there's no need to call the String(String)
constructor all over the place - just { "Car", "Bike" }
would be fine.)
One point to note about array variance: this is checked at execution time. For example:
Object[] x = { "x", "y", "z" };
x[0] = new Object(); // This is fine, because the array really is an Object[]
Object[] y = new String[] { "x", "y", "z" };
y[0] = new Object(); // This compiles, but throws an ArrayStoreException
// because the array is really a String[]
See more on this question at Stackoverflow