skiwi
skiwi

Reputation: 69259

Using equals() after serialization

I have the following method to convert a file (containing a serialized object) back into an object:

public static <T, C extends Class<T>> T readSerializableObjectFromFile(final Path path, final C clazz) {
    Objects.requireNonNull(path, "path");
    Objects.requireNonNull(clazz, "clazz");
    try (ObjectInputStream objectInputStream = new ObjectInputStream(Files.newInputStream(path))) {
        return clazz.cast(objectInputStream.readObject());
    } catch (IOException ex) {
        throw new UncheckedIOException(ex);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(ex);
    }
}

Say I have an object of type Organization, which has equals and hashCode methods, written in a file, what happens when I call the following?

Organization organization = 
    readSerializableObjectFromFile(myFile, Organization.class);

Does organization.hashCode() use the Object#hashCode or Organization#hashCode implementation?

And does the behaviour change when I store a List<Organization> in the file, and then retrieve it via

@SuppressWarnings("unchecked")
List<Organization> organizations =
    readSerializableObjectFromFile(myFile, List.class)

Upvotes: 0

Views: 1554

Answers (3)

Stephen C
Stephen C

Reputation: 718718

Say I have an object of type Organization, which has equals and hashCode methods, written in a file, what happens when I call the following?

When you call your readSerializableObjectFromFile method, one or more new objects are created, based on the state in the file. The fact that you have overridden hashcode and equals doesn't alter that fact.

Does organization.hashCode() use the Object#hashCode or Organization#hashCode implementation?

The version of hashCode() used is determined exactly the same way, whether or not it is the original object or a copy produced by serialization / deserialization.

And does the behaviour change when I store a List<Organization> in the file, and then retrieve it

No, it doesn't.


These questions are a bit strange ...

... but maybe what you are missing is that when you serialize and the deserialize an object using Java object streams, what you get is copies of the original object, and its closure. You don't get the same instances back ...

If your classes implement equals and hashCode to have "identity-based" equality semantics, then the copied objects are different objects and hence not be equal. But if your equals and hashCode to have "value-based" equality semantics, the copied objects should have the same "value" ...

Upvotes: 1

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95469

Because of dynamic dispatch, whenever you invoke a method like hashCode() or any other method, the particular function that is called depends on the runtime type of the object (not the declared type of the object). The ObjectInputStream/ObjectOutputStream will preserve the runtime type of objects (the runtime class is written on serialization and is thus used to instantiate the object on deserialization).

Your cast operation just checks that the result is of the correct type (it isn't the reason that the deserialized data is of that type), and it isn't causing the data to be converted or truncated (if that was what you were worried or concerned was happening here).

As for List<T>, the hash method is not tied to a particular type argument. The fact that the type was erased (which is how the structure is internally represented, anyway) does not change the behavior.

Upvotes: 2

It doesn't matter how object was created (directly using constructor, deserialized or via clone). If class of this object defines hashCode (or equals) that method will be used.

Upvotes: 0

Related Questions