Hi, Chan.
Chan Ag wrote:... I do not understand the dependency of this method with the readObject method. I understand it is package private so that immutability cannot be compromised upon to a certain extent ( or would that be wrong? ). But still, why is the method required, remains a puzzle to me.
It is needed in that particular implementation of the readObject method. As you can see, HashMap uses custom serialization protocol (I'll give a reason to do so below). When reading an object, it reads list of keys and values and puts it to a map (using map's own method). Any child should be prepared at this point. For example, LinkedHashMap uses a dummy head/tail values to unify item handling when map is or is not empty. If that dummy values are not initialized, insertion method may throw NullPointerException. And parent dsserialization occurs before child can perform any action. Other approaches are possible. But some approaches will require to reimplement readObject method in each children, for example.
Chan Ag wrote:And why should it be called if 'the constructor will add the entries from the existing map'. I see it is called by other constructors too.
Just because "copy constructor" and children constructor (notably LinkedHashSet) is implemented in some particular way. It is a contract between HashMap and very limited number of it's children. Some HashMap constructors calls internal methods to add all items. Child should be prepared at this point (for example, it should have a linked list initialized). Parent constructors must be called before any children constructor, so LinkedHashSet have no other chances to initialize. It is still possible to do that initialization other way. For example, call a parent's (HashMap) no-arg constructor, initialize internal data and only then call a package-private population method.
These are not coding choices. There are architectural choices. There may be many restrictions and considerations. And while some details are not included in a public API, they may be choosen arbitrary. These may be not the best solutions (and Collections framework ir relatively old), but they still work and there is no reason to change that decisions now.
Chan Ag wrote:Am I missing something here?
As I promised, default serialization is unsafe. I suggest "Effective Java", Chapter 10 "Serialization". In short, all fields read by default deserialization procedure must be considered public. For example you wrote a linked list. Then you may change some bytes in serialized form and read back a loop instead of list! Default serialized form may not be compatible with future class changes. Due to all this you always should consider writing writeObject/readObject methods and using your custom serialized form. HashMap writes a number of entries and then all key-value pairs in iteration order. This allows to change an internal implementation, because serialized form is independent from any internal representation. This also requires to properly reconstruct an object. And that, in order, requires that object to be in an appropriate state to accept new items (linked list initialized in child, etc...).