Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In immutable class why fields are marked as private?

What is the benefit of making fields private while creating an immutable class?

I have seen why while creating immutable class, fields are declared as private? but I didn't get understand anything from this post.

Can anybody please explain me the same?

like image 913
Sagar Pudi Avatar asked Feb 09 '15 12:02

Sagar Pudi


People also ask

Why are fields in a class marked private?

Fields should be declared private unless there is a good reason for not doing so. One of the guiding principles of lasting value in programming is "Minimize ripple effects by keeping secrets." When a field is private , the caller cannot usually get inappropriate direct access to the field.

Does immutable class have private constructor?

yes, using factory method. Using factory method doesn't assist but private constructor assist in achieving immutability. there are other things to be done when using private constructor which do not assist. Private constructor is just one of the ways for immutability and not the best one.

Why are immutable fields final?

An object (class or instance) is immutable, if its internal state cannot be changed (reflection doesn't count). Making a field final guarantees only that the value (if it's a primitive) or reference (for non-primitives) cannot be changed.

Why would one want to make fields immutable?

Immutable objects are thread-safe so you will not have any synchronization issues. Immutable objects are good Map keys and Set elements, since these typically do not change once created. Immutability makes it easier to parallelize your program as there are no conflicts among objects.


4 Answers

The best way to explain is with an example:

  public class Immutable {
     private final char[] state = "Hi Mom".getChars();
     
     public char[] getState() {
         return state.clone();
     }
  }

Here we have a properly encapsulated, immutable class. Nothing can change the state (modulo nasty reflective tricks).

Now lets JUST change the access on the field:

  public class Immutable {
     public final char[] state = "Hi Mom".getChars();
     
     public char[] getState() {
         return state.clone();
     }
  }

Note we are still making the defensive copy in getState ... as before ... but now someone can do this:

  Immutable mu = new Immutable();
  mu.state[1] = 'o';

... and our supposedly immutable object's state has changed.

That is ONE reason why it is a good idea to keep the fields private. (Obviously, this only applies to field whose types are mutable reference types.)

A SECOND reason is encapsulation. Declaring fields as private hides implementation details, which reduces the risk of unwanted cross-coupling. If I don't do this, then I (or some other programmer) might be tempted to write code that depends on the internals of Immutable. That is going to lead to problems if I need to change them; e.g. changing the type of state to String. Problems as in "lots more code to check / change".

A THIRD reason is that non-private (and particularly public) fields can be an impediment to subclassing. If I declare a field as public then, the I can't undeclare it in a subclass. If I want to hide the field or modify the behavior of the field in a subclass (by overriding) ... I can't. By contrast, if the field is private and access is via instance methods, I can override those methods in subclasses. Or I can choose to not use the field at all.

like image 54
Stephen C Avatar answered Oct 06 '22 03:10

Stephen C


The only reason for making final fields private is binary compatibility, and this actually holds true irrespective of whether the containing class is immutable or not.

A class C is said to offer binary compatibility to classes X and Y that use class C if class C can be refactored without having to recompile classes X and Y.

You only need to worry about binary compatibility if you are developing a library to be used by software that is written by others and therefore you have no control over. If you are in this situation, then you pretty much have to use full encapsulation, which means that you have to make all fields private and only access them via getters.

However, in the vast majority of cases, what we are developing is top-layer, self-contained application software, not libraries to be used by others. So, in the vast majority of cases, there is no good reason to make final fields of immutable classes private, it is just a widely held misconception. In a top-layer, self-contained application scenario you can always refactor everything and your IDE will accordingly refactor all references, so immutable classes do not need encapsulation.

Some of the answers suggest that if a field is not private, and it points to a mutable object, then someone might go and modify that mutable object, which is of course correct, but then we go into the philosophical question of what really is an immutable object. Can an object still be called immutable if it contains mutable objects? Is the mutability of an object dependent on the mutability of objects that it contains?

My rule is as follows:

There are two kinds of fields: contained and referenced, which can otherwise be thought of as owned and unowned. As an example, think of an Employee class: the name of the employee is contained/owned by the class, since each employee has their very own name. However, the Employee class may also contain a reference to a Department class, and of course each employee does not have their very own department, so the department is a referenced/unowned field.

A contained/owned field like Employee.name must of course be final and immutable in order for the owning class (Employee) to be immutable. Such a field does not need to be private, unless we are aiming for binary compatibility.

A referenced/unowned field like Employee.department also needs to be final if the referring class (Employee) is to be immutable, but it does not have to be immutable, and its immutability does not affect the immutability of the referring class. Even in this case, (and unless we are aiming at binary compatibility,) a referenced/unowned field generally does not need to be private, because there is still no issue of encapsulation: we are not going to be making a defensive copy of an employee department, that would be nonsensical.

So, unless we are aiming for binary compatibility, then both in the case of contained/owned immutable fields and referenced/unowned fields (which can be either mutable or immutable,) the fields can stay public final and everything will be fine.

like image 43
Mike Nakis Avatar answered Oct 06 '22 03:10

Mike Nakis


final class A{
   final List l = new ArrayList(); 
}

Suppose you have list, and you made this list as final it's reference not modified at all.

But this list is easily accessible to outer classes and they are easily modify it's contents.

so prevent that we have to add private access specifier.

like image 39
atish shimpi Avatar answered Oct 06 '22 03:10

atish shimpi


An object that is referred to by a public final reference-type field can still be modified through that field. (What you can't do is change the field to refer to a different object.)

To disallow unwanted modifications, you need to make the field private.

like image 23
Bathsheba Avatar answered Oct 06 '22 05:10

Bathsheba