Java Reference
In-Depth Information
Determining the Class of a Deserialized Object
Clearly, since the
readObject()
method returns the object that it reads from the stream as type
Object
, you need to know what the original type of the object was in order to be able to cast it to its
actual type. For the most part, you will know what the class of the object is when you read it back. It is
possible that in some circumstances you won't know exactly, but you have a rough idea, in which case
you can test it. To bring the problem into sharper focus let's consider a hypothetical situation.
Suppose you have a file containing objects that represent employees. The basic characteristics of all
employees are defined in a base class,
Person
, but various different types of employee are represented
by subclasses of
Person
. You might have subclasses
Manager
,
Secretary
,
Admin
, and
ShopFloor
for instance. The file can contain any of the subclass types in any sequence. Of course, you can cast any
object read from the file to type
Person
because that is the base class, but you want to know precisely
what each object is so you can call some type specific methods. Since you know what the possible types
are you can check the type of the object against each of these types and cast accordingly.
Person person = null;
try {
person = (Person)objectIn.readObject();
if(person instanceof Manager)
processManager((Manager)person);
else if(person instanceof Secretary)
processSecretary((Secretary)person);
// and so on…
} catch (IOException e){
}
Here we determine the specific class type of the object read from the file before calling a method that
deals with that particular type of object. Don't forget though that the
instanceof
operator does not
guarantee that the object being tested is actually of the type -
Manager
say. The object could also be of
any type that is a subclass of
Manager
. In any event, the cast to type
Manager
will be perfectly legal.
Where you need to be absolutely certain of the type, you can use a different approach:
if(person.getClass().getName().equals(Manager))
processManager((Manager)person);
else if(person.getClass().getName().equals(Secretary))
processSecretary((Secretary)person);
// and so on…
This calls the
getClass()
method (inherited from
Object
) for the object read from the file and that
returns a reference to the
Class
object representing the class of the object. Calling the
getName()
method for the
Class
object returns the fully qualified name of the class. This approach guarantees that
the object is of the type for which we are testing, and is not a subclass of that type.
Another approach would be to just execute a cast to a particular type, and catch the
ClassCastException
that is thrown when the cast is invalid. This is fine if you do not expect the
exception to be thrown under normal conditions, but if on a regular basis the object read from the
stream might be other than the type to which you are casting, you will be better off with code that
avoids the need to throw and catch the exception as this adds quite a lot of overhead.