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?
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.
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.
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.
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.
public fields can be accessed from any class anywhere and modified. But making fields private and final and using constructor injection / defensive copies, you ensure that the class is completely immutable.
Non-private fields may still be read-accessed - and if that field is an object, mutable operations on that object may be invoked.
Making the fields private will prevent this possibility.
If you'll use public field other objects will be able to change state of your "almost-immutable" object which will break encapsulation and make it a mutable object.
Related
I know the prerequisites for a class to be made immutable. I looked into the code, there were no setters for any variable defined in String. For StringBuffer and StringBuilder, there were two setters:
setLength which called the same named setters of parent AbstractStringBuilder.
setCharAt which manipulated the char value[] of parent AbstractStringBuilder.
String is "immutable" because its API (the public methods it defines) provides no way for a caller to change its state. Other classes, like StringBuilder, are mutable because they do provide "mutators", or methods that change the state of the class.
Under the covers there's nothing different between mutable or immutable objects. An object is just the primitive and reference values that make up its fields, and all fields are conceptually mutable (ignoring the final keyword for the moment). But by restricting the visibility of these fields (e.g. making them private) and defining methods that limit what a caller can do (like defining a getter but not a setter) you can provide a guarantee that instances of the class will be immutable, which is to say you promise none of its fields (or the objects they reference) will change over its lifetime.
By using the final keyword you can be even more explicit that a class is immutable. If you simply don't provide mutator methods, it's still possible for a class to be mutable if some private method mutates the class. If all the fields in a class are marked final, that's not (normally) possible. You can be confident any class with only final primitive (or immutable) fields is immutable*. That isn't the only way to guarantee immutability, but it is the clearest - any attempt to mutate the class would be a compiler error.
* The class itself also has to be declared final, otherwise someone could potentially create a mutable subclass. But again, there are other ways to ensure immutability. Using final everywhere is just the easiest to see.
There are a lot of things here.
All fields are private.
There are no setters / mutators.
Construction injection of arguments (using which String has to be constructed).
Reference to underlying char array (char[] value) does not leak out of this class.
Mutability is not merely defined by the presence or absence of setter/mutator methods.
In the case of StringBuilder and StringBuffer, there's a plethora of other methods (e.g. all the append() methods) that alter the internal state of the object, and hence make it mutable.
I have doubt a doubt regarding making an immutable class.
As per the java docs.
I made the class final( no one can extend)
field are private.
no setter function.
If fields are mutable then send a cloned copy of the field.
My doubt is that its compulsory to make a field of my class as final?
If there are no setter methods (and presumably no other methods to affect the fields' values) and the fields themselves are private, marking them as final is somewhat redundant.
Having said that - its a good defensive practice which many projects' standards follow.
Although as many say its not mandatory to mark the fields as final I would say atleast in one case that I can think of you need to mark the fields as final and that is in the case if you want to make your immutable class thread safe.
According to Java memory model:-
An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.
JLS final thread safety
So if you have an immutable class with instance variables which you initialize in constructor as non final variables then there is no guarantee of thread safety as the writes to the non final variables may not be visible to other threads even though the constructor has fully run ( Note recreating this is very difficult as this may occur in a highly concurrent application)
Immutable = not changeable. So making properties final is a good idea. If not all properties of an object are protected from being changed I wouldn't say the object is immutable.
BUT an object is also immutable if it doesn't provide any setters for it's private properties.
An immutable object will never change, but anything that it refers to might change.
Deep immutability is much stronger: neither the base object nor any object you can navigate to from it will change.
Recently I attended an interview.
I was asked how you can make a class Immutable.
I told him the answer.
But then he asked me why the fields are final?
I answered so that the user doesn't accidentally change the value of the field and it will give compiler error if he does so.
Now he ask me there is a immutable class with only getter methods.
Then in this class what is the use of final?
I was not able to answer. He told there is a reason behind that.
Can somebody explain?
From Effective Java:
Make all fields final. This clearly expresses your intent in a manner that is enforced by the system. Also, it is necessary to ensure correct behavior if a reference to a newly created instance is passed from one thread to another without synchronization, as spelled out in the memory model.
Now he ask me there is a immutable class with only getter methods.
Then in this class what is the use of final?
Only getter methods do not ensure that a class is immutable. If you expose the internal state than a client can change the class's state.
Immutable means that you can not change an objects state once it is created.
Making all fields final and providing only getters will not make it immutable out of the box. Imagine the following code:
public class MyString {
private final char[] content;
public MyString(String str){
this.content = str.toCharArray();
}
public char[] getContent(){
return this.content; // internal state exposed. You should return a copy.
}
}
This class has only final fields and only getter methods but is still mutable. Imagine this client code:
MyString myString = new MyString("test");
myString.getContent()[0] = 'f';
Now he ask me there is a immutable class with only getter methods.
Then in this class what is the use of final?
The use of final is to express your intention with java's language features and therefore enforce them by the compiler.
So making a variable final is good for primitive types, but you must take care if the variable is a reference. In this case you must either ensure that
the object you are referencing is also immutable or
only your instance has access to that object.
The later can only be ensured by the programmer. So take extra care when you return references.
Well, immutability is of course achieved in the way that an object is used, rather than by enforcement. You could always change a final field's value with Reflection.
The use of it is to allow the compiler to prevent you from breaking immutability, as well as to denote the need for immutability (such as when you use an inner class that uses a method-local reference).
'final' as the keyword's name suggest means that the attribute to which final keyword is attached can't be changed(in terms of value) in other words it behaves like a constant.if fields are not 'final' then inside local method you can change the value of fields.
Could you please clarify that why final keyword is required before class when we are making it an immutable one.
I mean, if we declare all of it's attributes as private and final, then also it is an immutable class, isn't it?
Sorry if the question seems easy, but i am truly confused about it. Help me out.
Editted:
I know that a class declared final can't be subclassed.. But if each attribute is private and final then what difference does that make?
As stacker says, final makes sure the class isn't subclassed. That's important so that any code which is relying on its immutability can do so safely.
For example, immutable types (where each field is also of an immutable type) can be freely used between threads without worrying about data races etc. Now consider:
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
That looks like you can share Person instances freely across threads with no problem. But what about when the object you're sharing is actually a mutable subclass:
public class Employee extends Person {
private String company;
public Employee(String name, String company) {
super(name);
this.company = company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCompany() {
return company;
}
}
Now instances of Employee aren't safe to share between threads, because they're not immutable. But the code doing the sharing may only know about them as instances of Person... leading them into a false sense of security.
The same goes for caching - it should be safe to cache and reuse immutable types, right? Well, it is safe to cache instances which are genuinely of an immutable type - but if you're dealing with a type which itself doesn't allow mutation, but does allow subclasses, it's suddenly not safe any more.
Think about java.lang.Object. It doesn't have any mutable fields, but it's clearly a bad idea to treat every Object reference as if it's a reference to an immutable type. Basically it depends on whether you think about immutability as a property of the type or of objects. A truly immutable type declares "any time you see a reference of this type, you can treat it as immutable" - whereas a type which allows arbitrary subclassing can't make that claim.
As an aside, there's a half-way house: if you can limit the subclassing to only "trusted" places, you can ensure that everything's immutable, but still allow that subclassing. The access in Java makes that tricky, but in C# for example you could have a public class which only allowed subclassing within the same assembly - giving a public API which is nice and strong in terms of immutability, while still allowing for the benefits of polymorphism.
A class that is declared final cannot be subclassed. See also http://docs.oracle.com/javase/tutorial/java/IandI/final.html
The different semantics of all uses of the final keyword are described in the The Java Language Specification
4.12.4 final Variables Page 80
8.1.1.2 final Classes Page 184
8.3.1.2 final Fields Page 209
8.4.3.3 final Methods Page 223
You don't strictly need final to make an immutable class. i.e. you can make an immutable class without it being final.
However, if you don't make it final, then it is possible for someone to extend a class and create a subclass that is mutable (either by adding new mutable fields, or overriding methods in a way that enables you to mutate protected fields of the original immutable class). This is a potential problem - it violates the Liskov Substitution Principle, in the sense that you would expect the property of immutablity to be preserved by all subtypes.
Hence, it is usually good practice to make immutable classes final to avoid this risk.
'final' as the keyword's name suggest means that the attribute to which final keyword is attached can't be changed(in terms of value) in other words it behaves like a constant.
As per your question if all members of the class is made private and final but the class is not made final then the same class can be inherited but the super class member are immutable as final keyword is attached to them.
An immutable object is an object which state is guaranteed to stay identical over its entire lifetime. While it is perfectly possible to implement immutability without final, its use makes that purpose explicit, to the human (the software developer) and the machine (the compiler).
Immutable objects carry some very desirable characteristics:
they are simple to understand and easy to use
they are inherently thread-safe: they require no synchronization
they make great building blocks for other objects
Clearly final is going to help us define immutable objects. First in labelling our object as immutable, which makes it simple to use and understand by other programmers. Second in guaranteeing that the object's state never changes, which enable the thread-safe property: thread concurrency issues are relevant when one thread can change data while another thread is reading the same data. Because an immutable object never changes its data, synchronizing access to it is not needed.
Create an immutable class by meeting all of the following conditions:
Declare all fields private final.
Set all fields in the constructor.
Don't provide any methods that modify the state of the object; provide only getter methods (no setters).
Declare the class final, so that no methods may be overridden.
Ensure exclusive access to any mutable components, e.g. by returning copies.
A class declared final cannot be sub classed. Other classes cannot extend final class. It provides some benefit to security and thread safety.
If all public and protected methods are final and none of them allows modifying private fields, and all public and protected fields are both final and immutable, then I guess it could be said class is semi-immutable, or sort of constant.
But things break down when you create a subclass and need to override equals and hashcode. And can not because you made them final... So the whole thing is broken, so just make the whole class final to prevent programmer from being a fool by accident.
As an alternative to doing this kind of bastardized version immutability, you have several options.
If you want to attach extra data to immutable instance, use Map. Like if you wanted to add age to name, you would not do class NameAge extends String... :-)
If you want to add methods, create a class of static utility functions. That is a bit klunky, but it is the current Java way, Apache commons for example is full of such classes.
If you want to add extra methods and data, create a wrapper class with delegate methods to methods of the immutable class. Anybody needing to use the extra methods needs to be aware of them anyway, and there is not much practical difference in casting to derived non-immutable class or doing something like new MyWrapper(myImmutableObj) for many use cases.
When you really have to have reference to original imutable object (like storing it in existing class you can not change), but need the extra data somewhere, you need to use the Map approach to keep the extra data around, or something like that.
If an immutable class Foo is sealed ("final"), then anyone who receives a reference to a Foo may be assured that if Foo was implemented correctly, the referenced instance will in fact be immutable. If an immutable class is not sealed, then someone who receives a reference to a Foo may be assured that if the actual class of of the referenced object (which may be Foo or some derivative type implemented by some arbitrary unknown person) was implemented correctly, the instance will be immutable. Leaving Foo unsealed means that anyone who relies upon Foo to be immutable will have to trust that everyone who writes a class that derives from Foo will implement it correctly. If one wants to be certain that every reference to a Foo will in fact target an immutable instance without having to rely upon the authors of derivative classes to abide by the contract, making Foo final can aid in such assurance.
On the other hand, the possibility that a class might derive from Foo but violate its immutability isn't terribly different from the possibility that a class which derives from any other class might violate the contracts of its parent class. Any code which accepts a reference of any type which can be subclasssed by outside code might be given an instance of a subclass which violates its parent's contract.
The fundamental question when deciding whether an immutable class should be sealed is the same as for any other class: whether the benefits of leaving the type unsealed outweigh any dangers that would be posed by doing so. In some cases, it may make sense to have an extensible immutable class, or even an abstract class or interface whose concrete implementations are all contractually obligated to be immutable; for example, a drawing package might have an ImmutableShape class with some concrete fields, properties, and methods to define 2D transformations, but an abstract Draw method, allowing for the definition of derivative types ImmutablePolygon, ImmutableTextObject, ImmutableBezierCurve, etc. If someone implements an ImmutableGradientFilledEllipse class but fails to have that type make its own copy of a mutable GradientColorSelector, the colors of gradient-filled polygons might change unexpectedly, but that would be a fault of the ImmutableGradientFilledEllipse class, and not the consuming code. Despite the possibility of a broken implementation failing to uphold the "immutability" contract, an extensible ImmutableShape class would be much more versatile than a sealed one.
I marked an immutable data model class as final to make sure the only way to change its values is to create a new instance. (Unfortunately, the fields cannot be final because they needs to be populated by Hibernate.)
This worked well until I wanted to check another class throws the correct exception when called with an invalid instance of the model. The constructor of the model validates the arguments so reflection must be used to set the fields. This is extremely clumsy since the model have quite a few fields and the field names have to be hard-coded.
I can't mock the model either due to it being final. (Is it also debatable whether an interface should be used to enable mocking while keeping the class immutable. By having an interface, there's no way to programmatically mandate the methods must return the same value throughout the life of the instance.)
What do people usually do in this case? Is there any standard approach to this?
Generally speaking, you shouldn't want to mock data objects. Data objects should have no logic and no external dependencies, so there's not really much use to mocking the objects. Instead make it very easy to create fake instances that you can populate in methods as you'd like.
Furthermore, there are a few other reasons you might want to avoid treating a Hibernate-persisted object as immutable:
Hibernate-provided objects are inherently not thread-safe and therefore lose the thread-safety advantages that immutable value objects typically provide.
You may find your objects are actually proxies, possibly undercutting the final semantics.
Hibernate-controlled objects operate completely differently whether their session is still open (attached vs detached) making them a very poor choice for an immutable object. If your immutable object depends on session lifetime, it's not really immutable.
It sounds like some objects may be valid or invalid at the application layer, beyond database-layer validation. That makes it a little harder to encapsulate your validation concerns.
You are required to have a public no-arg constructor, which is antithetical to the kind of instance control typical of immutable value objects.
Because the objects are inherently mutable, it is more complicated to override equals and hashCode.
My advice? If you need more immutability and data validation guarantees than a Hibernate DAO can grant you, then create a real final immutable class with final fields (or a private constructor and static factory method), and then make a constructor (or static factory method) that copies in values from your Hibernate DAO.
If you decide this option, you are stuck with the overhead of having two data objects that change roughly in parallel, but you also get the benefit of separating concerns (in case the Hibernate object should diverge) and the ease of a truly-immutable, equals-and-hashcode-overriding, session-agnostic, guaranteed-valid object that you can easily create for tests.
For clarity, making a class final prevents it from being sub-classed. This is good in cases where the class doesn't need to be further refined.
Marking a class level variable as final means that it will only get assigned once. For primitives and immutable objects like String, this has the side effect of making the variable immutable (by default).
However, for mutable objects like Date, your variable will always reference the same instance, but others with access to that instance would still be able to change it's state. For example if you had a method
public Date getCreatedDate(){
return this.created; // class variable declared as private final Date created...;
}
Then any caller could access the created instance and change it's state. You would be better to only return truly immutable values, or return a clone.
public Date getCreatedDate(){
return this.created.clone();
}
EDIT
"I marked an immutable data model class as final to make sure the only way to change its values is to create a new instance"
Your issue as I understand it is that Class A has a dependency on Class B. You wish to test class A and you are unable to mock class B, as you have marked it as final. You marked Class B as final to make it immutable (preventing it's internal state being changed). This is incorrect, as marking a class final prevents it from being sub-classed. It has nothing to do with the ability to change the internal state of an instance.
Your use of final does not have the desired effect. Marking the fields as final is not an option, and would not make the class immutable for the reasons stated above. The only way to protect your data is to prevent clients of your data from having access to the objects that make up it's internal state.
Assuming, that you won't be the only developer, you need to protect the users of your data from unintentional updates. Ensuring that you return clones from getters is one approach. Having team members sub-class and change data is just bad programming, not unintentional, and could be managed through policy and code review.
If you wish to protect your code from external interference by unknown developers (for example writing code that utilises the same namespace to inject their code), then other approaches are available such as package sealing.