As the title says , Why are the instance variables are declared as private in immutable pattern ? I think that the keyword final is enough to avoid any changes that can be done to the value of the instance variable. So why do we also use private keyword with it ?
An object has the potential for (at least) two aspects:
- a set of members intended for consumption by an external consumer, a public face, and,
- implementation details many of which are hidden or restricted in various ways
Private is used to label members that are emphatically not ones that a consuming client is allowed to interact with it — such members are encapsulated within the broader object.
The ability to restrict the ways external code interacts with an abstraction is a key helper in providing guarantees useful in maintenance — as someone maintaining the code, we can rest assured that no one (else) in the whole project is (capable of directly) consuming those private members, so we'll never find any references to them from other code.
Final/readonly is an orthogonal concept — allowing readonly access to your instance variables makes them part of the object's client-consumable members.
For example, we can delete a private instance variable, or change its type, and know for certain that we only have to work with that one class — we will not have to worry or reason past the class itself. Whereas if a final public member is deleted or its type changed, we will have to concern ourselves with consuming clients (meaning they will have to be modified and as they are possibly other things may also end up requiring changes).
This can be of varying severity, ranging from not to big a deal for a small program whose source code always versioned together, built, and tested — to probably most critical when a library doesn't have access to the client code that is consuming it, especially when a new version of libraries can be installed/upgraded on a user's machine without any build & test event.