0

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));


        }
    }
1
  • because instances cast to the same type they origin of like humans they are citizen. Commented Feb 27, 2014 at 22:58

4 Answers 4

2

In your first example, you create an object of type Object[], and cast it to String[]. Since Object[] doesn't extend String[], the cast fails. That's like wanting to cast a Banana to Apple. A banana is not an apple, so the cast fails.

In the serialization example, an object of type String[] is serialized, and then deserialized. The serialization mechanism consists in writing the type of the object, and then its state. When deserializing , it recreates an object of the same type (String[]), and then populates it with the state read. The object is thus a String[], and casting a String[] to String[] works fine.

Sign up to request clarification or add additional context in comments.

Comments

1

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[]

7 Comments

"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." can you elaborate what you mean by this?
@user1988876: your statement is equivalent to Object[] o = new Object[] {"a", "b"}, not to Object[] o = new String[] {"a", "b"}
@user1988876: I mean that even though you've specified string elements, in the array initializer, it's still creating an object of type Object[], because that's how the variable (objArr) was initialized - whether it explicitly uses new String[] or not. See my two examples, which differ only in the declaration type of x.
@JBNizet: Nice clarification - I'll edit that into my answer. (Not sure why it's been downvoted, but never mind.)
I upvoted it, because it doesn't deserve the downvote, and provides valuable information.
|
1

Java arrays are a little strange. A String[] is castable to Object[]. It is still has the runtime type of String[], so if you cast and then try to put a non String object in it, you'll get a runtime error.

Serialization takes the runtime type into account, so it saves the fact that you've given it a String[], even though the "arr" variable is of type "Object[]", it holds a "String[]"

ois.readObject() in this case will reconstruct a String[].

Comments

0

Case 1:

Object[] objArr = {new String("hello"), new String("world")};
String[] arr = (String[]) objArr;
  • You can put to objArr everything not only Strings.
  • Array of Strings can contains only Strings

That is why casting String[] to Object[] is illegal.

Case 2:

String[] strArr = {new String("hello"), new String("world")};
Object[] arr = strArr; // you do not even need to cast
  • Every String is an Object

So everything you will get from the array of Object[] is an Object, that why it's legal.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.