I need to develop a Java RMI application for my distributed systems class.
During the lecture, the professor was stressing to only let classes implement Seriali
only let classes implement Serializable that have to be passed by value over the network.
Your professor is suggesting you minimize your use of Serializable
to areas where it's strictly needed.
This is because serialization is a strong candidate for leaking implementation. Implementing Serializable
shows intent of serialization (even if the object is never actually serialized), which imposes the idea that developers should take caution when modifying those classes to avoid breaking software.
Joshua Bloch covers this in his book Effective Java.
The moment you serialize an object, the class that it was instantiated from can no longer be modified without special treatment†. If you modify the class, the binary representation will no longer match the objects already serialized. Thus deserialization of any objects serialized before modifying the class will fail.
If a type implements Serializable
, it has the potential to be serialized. If an instance of that type was serialized, you may break code by modifying it's implementation.
Since there's no easy way of knowing for sure that an instance of a serializable type has been serialized (albeit you may not intend for objects to be serialized), developers take strong caution when modifying implementations of those types.
† - This could be avoided by properly versioning your serializable types, but due to the potential of versioning a type that had no contract change (with no compile time error handling support to notify you), it's best to keep explicit versioning minimal to avoid adding excess complexity to your design.
What is the penalty for unnecessarily implementing Serializable?
There is no penalty for unnecessarily implementing Serializable
. If you never serialize the object, nothing happens just because you added implements Serializable
. If you do serialize it, it works instead of failing. That's not a penalty.
Why the professor was stressing that is a mystery. Ask him. There is no overhead other than when serializing, and if you're passing objects by value via RMI you don't have any choice but to implement Serializable
, so there is nothing to evalute the overhead against. It is meaningless.
I would understand the professor's "only let classes implement Serializable that have to be passed by value over the network" differently. I would think the idea is that if you have to use a class in this way then make your own implementation of writeObject, readObject and readObjectNoData, which could be more efficient than the default implementation.
If someone later want to subclass your serializable class, they will have to make sure that their class is indeed serializable too. That could require an effort they don’t want to do.
Say you have:
public class YourClass implements Serializable {
}
Now if I write:
class MyClass extends YourClass {
private SomeoneElsesClass myField;
}
and SomeoneElsesClass
is not serializable, my FindBugs will flag myField
with the message “Non-transient non-serializable instance field in serializable class”. I am trying to keep my code clean from warning messages, but in this case, I cannot.
I’m often specializing Swing classes. Sometimes I want to have instance fields of non-serializable classes, which basically introduces errors in my code. In real life I only get a warning message, and as long as the object isn’t actually serialized, it works; I’m still annoyed with those warning messages.