In my quest to make an object immutable in Java, I marked the class final, All of its variables final and provided no setters and getters. Will these provide sufficient guarantees that the object will not be modified ? Are all 3 necessary or 2 of the 3 conditions are more than enough ?
public final class MyClass
Has nothing to do with immutability, it only disallows inheritance.
Just marking variable references final is not enough, every object you refer to has to be immutable as well.
final doesn't make an object immutable, it makes the references immutable;
private final List<String> strings = new ArrayList<String>();
strings is still a mutable List, only the reference to the List is immutable.
Be careful with things like:
Collections.unmodifiableList(strings);
Collections.unmodifiableList() JavaDoc provides a "unmodifiable view" but it still doesn't guarantee that the underlying list could not be changed by an external reference to the original List that is being wrapped. A deep copy of the list contents would have to be made into a new list and that list wrapped with unmodifiable.
And every instance of every object and all their children and children's children have to be immutable as well.
Marking your fields final is the only option you need out of the mentioned set. You can provide getters, but be careful about mutable sub-objects like collections. Final makes the reference immutable but not the contents. A useful technique with getters is to make a defensive copy if the value is mutable like so:
public class ImmutableExample{
private final int value1; // immutable
private final List<Integer> value2; // contents will not be immutable
public ImmutableExample(...){...} // be careful here to copy the collection as you want to disalow any outside modification.
public int getValue1(){
return value1;
}
public List<Integer> getValue2(){
return Collections.unmodifiableList(value2);
}
}
Another option is to use Google Guava collections that include Immutable collections as we discussed here: Immutable objects and unmodifiable collections. These result in really easy immutable classes:
public class ImmutableExample{
private final int value1; // immutable
private final ImmutableList<Integer> value2; // immutable
public ImmutableExample(...){...}
public int getValue1(){
return value1;
}
public List<Integer> getValue2(){
return value2;
}
}
Marking your class as final you're only telling that no one can subclass it.
That said, marking your variables as final would be enough, as long as your class had only 'primitive' attributes. It's ok (and encouraged) to keep the getters, however, you also may want remove the setters, since while you don't want any external class to mess around with your variables, setters won't be needed.
It would be more natural to set all variables private and only provide getters. You then need not set the class final which is unnecessary overkill.
Further consideration must be made if the fields are non-final objects themselves such as collections. You should only store copies of these.
Contrary to some of the comments here, making a class final does have to do with immutability. For a class to be immutable, it should be final, so as to not allow subclasses to override any getters, and thereby not allowing them to "mutate" it by returning a different value.
Recall that to guarantee immutability, a class must not permit itself to be subclassed.
- Joshua Bloch, Effective Java
also, from the Java tutorials, A Strategy for Defining Immutable Objects:
3.Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final
Related
I have an object such as
public class ABC {
private String a;
private String b;
private String c;
//getters and setters
}
This object is returned from a method in the collections such as ArrayList<ABC>.
I just want to make the return immutable without changing anything in the object. Can anyone please help me with this?
Don't provide setters (mutators), make immutable attributes private, only provide value assignment via constructor.
You can always declare your immutable attributes final. So you can only assign them values once and can't change them later.
You cannot make an object immutable if its class provides for mutation. Objects always offer all the capabilities defined by their classes.
Therefore, if you want an immutable object then you need an immutable class. If you cannot change the class in question, then a wrapper class such as #duffymo described could serve that purpose. Note, however, that objects of such a class are not interchangeable with objects of the wrapped class, and also that somehow you need to provide for applying the wrappers.
If you need objects that are fully interchangeable with objects of class ABC, then you're stuck with the fact that ABCs are mutable, therefore anything interchangeable with ABCs is mutable, at least with respect to the mutable aspects of ABC. Then it comes down to why you want immutability. If the point is to avoid mutating the object referenced by the List, then copying those objects (to whatever depth is appropriate) is an alternative.
As a third alternative, if the target class has no non-private fields then you might be able to create a subclass, overriding the setters to be ineffective or to throw some variety of unchecked exception. In that case, note that
Such a subclass is not good form, and its instances are not truly interchangeable with instances of class ABC.
If class ABC has accessible properties of mutable types (e.g. mutable containers), then you may need to do something to prevent those objects from being mutated, too. Recursively.
Yes, this is a big mess.
Use interfaces with only getters
A is your concrete (impl) class
Coding to interfaces?
public I getA(){ retrun AImpl();}
where
public interface I { public String getOne()}
public AImple implements I {...}
The only "Change" in your current class would be "implements I"
JDK and Apache commons use decorators
http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.embedded/thirdparty-all/beta3.SP15/org/apache/commons/collections/list/UnmodifiableList.java
Another solution
Clone your object and return it, that way copy is changed and original object remains intact
Assuming we had this class
final class Foo {
private final Set<String> bar = new HashSet<>();
public Foo() {
bar.add("one");
bar.add("two");
bar.add("three");
}
public boolean contains(final String s) {
return bar.contains(s);
}
}
Would it be threadsafe to instantiate Foo and call contains of this object from multiple threads?
The reference to the collection is private and final. No one can access directly the collection.
The only write access occurs in the constructor
After the constructor is executed, the collection will only read and not modified.
If not, is there an pure Java alternative to Guava's immutable collections?
Your Foo and bar are actually immutable. it is thread-safe.
It depends on how the access to this object is published. While the bar Set is final and thus guaranteed to visible to all threads, the population of the map is not guaranteed to happen before the conclusion of constructor.
This, however would be guaranteed to be thread safe regardless of how the object was created and made available.
private final Set<String> bar;
public Foo() {
bar = new HashSet<String>(Arrays.asList("one", "two", "three"));
}
Testing initialization safety of final fields
https://stackoverflow.com/a/23995782/676877
It is thread safe provided that
1) The constructor does not leak a reference before its fully constructed.
2) No one has any way to access the collection.
3) No subclass can be created which can edit the collection.
As a general rule though, if you want to implement this use an immutable collection from guava, that makes the behaviour explicit to the programmer, and it is then safe to return the whole map. I think that in pure java you can return an unmodifiable view of a collection.
As long as this is accessed in a read only manner I think you should be safe. Also , java offers immutable versions of it's base collections exposed through static methods on the Collections class , so I would look at Collections.unmodifiableSet() .
Also , while you add strings in your example, and strings themselves are immutable in java , you would be in trouble if you added mutable objects and then decided to modify/read them from different threads (you would need synchronized blocks in this case).
If I have a class like that:
public class MyObject {
private int myField = 2;
public void setMyField(int f) {
this.myField = f;
}
}
Will objects of this class be mutable?
Thanks!
Of course - if you want it to be immutable, then you need something like:
public class MyObject {
private final int myField;
public MyObject(int f) {
myfield = f;
}
public int getMyField() {
return myField;
}
}
yes
Mutable objects have fields that can be changed, immutable objects
have no fields that can be changed after the object is created.
You already have several answers with a "Yes".
I would like to add a "but" (if I would be bold, I would say "No" ;-)
Yes, an object of this class appears to be mutable, since it provides a setter to change the field. However, since it does not have a getter for that field, neither any other getter depending on that field, and since the field is private, it is currently not possible to read that state.
Put differently: The object has state, but it does not expose any state to the outside.
I would call that object "effectively immutable".
There are some design patterns, where objects are "effectively immutable", for example "Lazy Initialization" of an "Immutable Object".
Note: The concept of being "effectively immutable" is discussed in Section 3.5.4 of Java Concurrency in Practice by Brian Goetz.
Yes, objects of this class are mutable. The designer of the class can't prohibit by any technical means (in real existing Java) consumers of the objects to observe and modify the contents of the field.
private is an explicitly declared contract regarding intended usage of the field - this contract can be broken, e.g. with reflection.
Not providing any methods that change the data of an object after creation can also be a (implicitly declared) contract about intended use and mutability - this contract, too, can be broken, like any contract that needs two conforming parties.
Edit: Unless there is another party that has the means to enforce - like in Java the SecurityManager stopping you from changing a final field at runtime.
Yes, your object is mutable as the value of myField can be changed after the instance is created using the setter.
Immutability can be achieved using final fields, as it will not allow you to change the value of a variable once it is initialized.
Answer by #JakubK points out how you can make your class Immutable.
But declaring reference final wont make the object being pointed by it final.
For example:
class MyObject{
private final List<Integer> list = new ArrayList<Integer>();
public List<Integer> getList(){
return list;
}
}
I can change add a new element to the list from outside by doing something like this
instance.getList().add(1); //mutates the list
This example is not immutable, as the List can be changed by someone else.
To define whether something is mutable, one has to define what state is encapsulated thereby. If MyObject specifies that its state includes the value which Reflection will report for myField, then it is mutable. If that field is not specified as being part of the object's observable state, then it may be most purposes regarded as immutable.
To be more specific, I would regard a class as being immutable only if one could perform any combination of documented operations upon the class, in any sequence and with any timing (even on multiple threads), and not have any documented behavioral aspects of of any of them affected by any other. The fact that a method might change the contents of a private field is relevant if and only if that change would affect some documented behavioral aspect of another method call (to the same or different method). For example, I would say that the fact that String.hashCode() modifies the hash field does not make String mutable, because the value returned by hashCode() is not affected by whether or not the field had been written previously. If a class had a hashCode method which would, if a field was blank, generate a random number and store it in that field, and otherwise return the value directly, such a class would be mutable unless it ensured that the field was tested and set as an atomic operation. In the absence of such assurance, it would be possible for near-simultaneous calls to hashCode() to yield different values, and thus for future calls to differ values that would differ from at least one of them (implying that the object's state had changed between the call that returned the odd-ball value and the later call).
I already know the definition of immutable classes but I need a few examples.
Some famous immutable classes in the Standard API:
java.lang.String (already mentioned)
The wrapper classes for the primitive types: java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float
java.lang.StackTraceElement (used in building exception stacktraces)
Most enum classes are immutable, but this in fact depends on the concrete case. (Don't implement mutable enums, this will screw you up somewhen.) I think that at least all enum classes in the standard API are in fact immutable.
java.math.BigInteger and java.math.BigDecimal (at least objects of those classes themselves, subclasses could introduce mutability, though this is not a good idea)
java.io.File. Note that this represents an object external to the VM (a file on the local system), which may or may not exist, and has some methods modifying and querying the state of this external object. But the File object itself stays immutable. (All other classes in java.io are mutable.)
java.awt.Font - representing a font for drawing text on the screen (there may be some mutable subclasses, but this would certainly not be useful)
java.awt.BasicStroke - a helper object for drawing lines on graphic contexts
java.awt.Color - (at least objects of this class, some subclasses may be mutable or depending on some external factors (like system colors)), and most other implementations of java.awt.Paint like
java.awt.GradientPaint,
java.awt.LinearGradientPaint
java.awt.RadialGradientPaint,
(I'm not sure about java.awt.TexturePaint)
java.awt.Cursor - representing the bitmap for the mouse cursor (here too, some subclasses may be mutable or depending on outer factors)
java.util.Locale - representing a specific geographical, political, or cultural region.
java.util.UUID - an as much as possible globally unique identifier
while most collections are mutable, there are some wrapper methods in the java.util.Collections class, which return an unmodifiable view on a collection. If you pass them a collection not known anywhere, these are in fact immutable collections. Additionally, Collections.singletonMap(), .singletonList, .singleton return immutable one-element collections, and there are also immutable empty ones.
java.net.URL and java.net.URI - representing a resource (on the internet or somewhere else)
java.net.Inet4Address and java.net.Inet6Address, java.net.InetSocketAddress
most subclasses of java.security.Permission (representing permissions needed for some action or given to some code), but not java.security.PermissionCollection and subclasses.
All classes of java.time except DateTimeException are immutable. Most of the classes of the subpackages of java.time are immutable too.
One could say the primitive types are immutable, too - you can't change the value of 42, can you?
is Class AccessControlContext a immutable class
AccessControlContext does not have any mutating methods. And its state consists of a list of ProtectionDomains (which is an immutable class) and a DomainCombiner. DomainCombiner is an interface, so in principle the implementation could do something different on each call.
In fact, also the behaviour of the ProtectionDomain could depend on the current policy in force - it is disputable whether to call such an object immutable.
and AccessController?
There are no objects of type AccessController, since this is a final class with no accessible constructor. All methods are static. One could say AccessController is neither mutable nor immutable, or both.
The same is valid for all other classes which can't have objects (instances), most famously:
java.lang.Void
java.lang.System (but this has some mutable static state - in, out, err)
java.lang.Math (this too - the random number generator)
java.lang.reflect.Array
java.util.Collections
java.util.Arrays
Immutable classes cannot be changed after construction. So, for example, a Java String is immutable.
To make a class immutable, you have to make it final and all the fields private and final. For example the following class is immutable:
public final class Person {
private final String name;
private final int age;
private final Collection<String> friends;
public Person(String name, int age, Collection<String> friends) {
this.name = name;
this.age = age;
this.friends = new ArrayList(friends);
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public Collection<String> getFriends() {
return Collections.unmodifiableCollection(this.friends);
}
}
I have added in a method in the code example showing how to handle collections, an important point.
Where possible you should make classes immutable, because then you don't have to worry about things like thread safety.
It's important to keep in mind that declaring a class as final does not means that it is "immutable", this basically means that this class cannot be extended (or specialized).
Immutable classes must have private and final fields (without setters), so after its construction, it cannot have its field values changed.
To create a class immutable, you need to follow following steps:
Declare the class as final so it can’t be extended.
Make all fields private so that direct access is not allowed.
Don’t provide setter methods for variables
Make all mutable fields final so that it’s value can be assigned
only once.
Initialize all the fields via a constructor performing deep copy.
Perform cloning of objects in the getter methods to return a copy
rather than returning the actual object reference.
An example can be found here.
We can also use Builder Pattern to easily create immutable classes, an example can be found here.
LocalDate, LocalTime and LocalDateTime classes (since 1.8) are also immutable. In fact, this very subject is on the OCAJSE8 (1Z0-808) exam, and that's precisely why I decided to treat it as not a mere comment.
All primitive wrapper classes (such as Boolean, Character, Byte, Short, Integer, Long, Float, and Double) are immutable.
Money and Currency API (slated for Java9) should be immutable, too.
Incidentally, the array-backed Lists (created by Arrays.asList(myArray)) are structurally-immutable.
Also, there are some border-line cases such as java.util.Optional (featured on the OCP exam, 1Z0-809), which is immutable if the contained element is itself immutable.
String is a good "real world" example of an immutable class. And you can contrast it with the mutable StringBuilder class.
Most of the Java classes used for reflection are immutable. And some of the others are "almost immutable": e.g. the classes that implement Accessible have just a setAccessible method that changes the state of the Accessible instance.
I'm sure there are lots more in the standard class libraries.
The Sun (Oracle) documentation has an excellent checklist on how to make an immutable object.
Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
Don't provide methods that modify the mutable objects.
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
From: http://download.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
The site also provides examples of its use in a concurrency context but immutability is also useful when writing libraries. It assures that callers to the library are able to only change what we allow them to.
Immutable class is a class which once created, it’s contents can not be changed. Immutable objects are the objects whose state can not be changed once constructed. Example- String & all java wrapper classes.
Mutable objects are the objects whose state can be changed once constructed.example- StringBuffer Once value changed memory location altered.
See below example -
public static void immutableOperation(){
String str=new String("String is immutable class in Java object value cann't alter once created...");
System.out.println(str);
str.replaceAll("String", "StringBuffer");
System.out.println(str);
str.concat("Concating value ");
System.out.println(str + "HashCode Value " + str.hashCode());
str=str.concat("Concating value ");
System.out.println(str + "HashCode Val " + str.hashCode());
}
public static void mutableOperation(){
StringBuffer str=new StringBuffer("StringBuffer is mutable class in Java object value can alter once created...");
System.out.println(str + "HashCode Val - " + str.hashCode());
str.replace(0, 12, "String");
System.out.println(str + "HashCode Val - " + str.hashCode());
}
I like to use examples that have a mutable property. This helps understand how immutable classes truly function.
Mutable class
class MutableBook {
private String title;
public String getTitle(){
return this.title;
}
public void setTitle(String title){
this.title = title;
}
}
And an immutable implementation using the mutable instance of a book.
public class ImmutableReader {
private final MutableBook readersBook;
private final int page;
public ImmutableReader(MutableBook book) {
this(book, 0);
}
private ImmutableReader(MutableBook book, int page){
this.page = page;
// Make copy to ensure this books state won't change.
MutableBook bookCopy = new MutableBook();
bookCopy.setTitle(book.getTitle());
this.readersBook = bookCopy;
}
public MutableBook getBook() {
// Do not return the book, but a new copy. Do not want the readers
// book to change it's state if developer changes book after this call.
MutableBook bookCopy = new MutableBook();
bookCopy.setTitle(this.readersBook.getTitle());
return bookCopy;
}
public int getPage() {
// primitives are already immutable.
return page;
}
/**
* Must return reader instance since it's state has changed.
**/
public ImmutableReader turnPage() {
return new ImmutableReader(this.readersBook, page + 1);
}
}
In order for your class to be truly immutable, it must meet the following cirteria:
All class members are declared final.
All variables used in a class at the class level must be instantiated when the class is constructed.
No class variable can have a setter method.
This is implied from the first statement, but want to make it clear that you cannot change the state of the class.
All child object must be immutable as well, or their state never changed in the immutable class.
If you have a class with mutable properties, you must lock it down. Declare it private, and ensure you never change it's state.
To learn a little more take a look at my blog post: http://keaplogik.blogspot.com/2015/07/java-immutable-classes-simplified.html
While creating an object of an immutable class one must ensure that external reference will not be stored. However, the values does matter here. In the example given below, I have a class called Fruits inside there is a List. I have made the class immutable by making the List private and final as well as there is no setter provided.
If I am instantiating an object of Fruit, the constructor will be given a list.Client program does have a reference of this List already(client side) and hence the List can be modified easily and hence the immutability of the class will be lost.
To address this problem , I am creating a new List in the constructor which copies all the values supplied by the client.
Now if the client adds more values in the list, the external reference will get affected however, I am not storing that external reference anymore in my immutable class.
This can be verified by overriding an hashcode() in the immutable class. No matter how many times the client modifies the list the hashcode of my immutable class object will remain unchanged, as the list it accepts is no more pointing to the external list.
public class Fruit {
private final List<String> fruitnames;
public Fruit(List<String> fruitnames) {
this.fruitnames = new ArrayList<>(fruitnames);
}
public List<String> getFruitnames() {
return new ArrayList<>(fruitnames);
}
#Override
public int hashCode() {
return getFruitnames() != null ? getFruitnames().hashCode(): 0;
}
}
//Client program
public class ImmutableDemo {
public static void main(String args[]){
List<String> fruitList = new ArrayList<>();
fruitList.add("Apple");
fruitList.add("Banana");
//Immutable Object 1
Fruit fruit1 = new Fruit(fruitList);
//fruitHash is-689428840
int fruitHash = fruit1.hashCode();
System.out.println("fruitHash is" +fruitHash);
//This value will not be added anymore as the state has already been defined and
//now it cant change the state.
fruitList.add("straberry");
//fruitHash1 is-689428840
int fruitHash1 = fruit1.hashCode();
System.out.println("fruitHash1 is" +fruitHash1);
}
}
Is the below class immutable:
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
No it is not because the elements of the array can still be changed.
int[] v1 = new int[10];
MyClass v2 = new MyClass(v1);
v1[0] = 42; // mutation visible to MyClass1
My two cents regarding immutability rules (which I retained from reading Effective Java - a great book!):
Don't provide methods that can modify the state of an object.
Make all your fields final.
Make sure that your class is non-extendable.
Make all your fields private.
Provide exclusive access to any fields or components of your class that can be changed. Essentially this applies to your situation (as explained by JaredPar). A person that uses your class still has a reference to your array. The opposite is the case where you return a reference to an component of your class. In this case, always create defensive copies. In your case, you should not assign the reference. Instead, copy the array that the user of your class provides, into your internal component.
"Immutability" is a convention between the programmer and himself. That convention may be more or less enforced by the compiler.
Instances of a class are "immutable" if they do not change during the normal course of the application code execution. In some cases we know that they do not change because the code actually forbids it; in other cases, this is just part of how we use the class. For instance, a java.util.Date instance is formally mutable (there is a setTime() method on it) but it is customary to handle it as if it were immutable; this is just an application-wide convention that the Date.setTime() method shall not be called.
As additional notes:
Immutability is often thought of in terms of "external characteristics". For instance, Java's String is documented to be immutable (that's what the Javadoc says). But if you look at the source code, you will see that a String instance contains a private field called hash which may change over time: this is a cache for the value returned by hashCode(). We still say that String is immutable because the hash field is an internal optimization which has no effect visible from the outside.
With reflection, the most private of instance fields can be modified (including those marked as final), if the programmer wishes so hard enough. Not that it is a good idea: it may break assumptions used by other pieces of code using the said instance. As I said, immutability is a convention: if the programmer wants to fight himself, then he can, but this can have adverse side-effects on productivity...
Most Java values are actually references. It is up to you to define whether a referenced object is part of what you consider to be "the instance contents". In your class, you have a field which references an (externally provided) array of integers. If the contents of that array are modified afterwards, would you consider that this breaks immutability of your MyClass instance ? There is no generic answer to that question.
There is no way to make an array immutable. That is there is no way to keep any client code from setting or removing or adding items to the array.
Here is a truly immutable alternative:
private static class MyClass
{
private List<Integer> list;
private MyClass(final int[] array)
{
final List<Integer> tmplist = new ArrayList<Integer>(array.length);
for (int i : array)
{
tmplist.add(array[i]);
}
this.list = Collections.unmodifiableList(tmplist);
}
}
To make a class immutable, you need to both ensure that all the fields on it are final, and that the types of those fields are immutable too.
This can be a pain to remember, but there is a tool to help you.
Pure4J provides an annotation #ImmutableValue, which you can add to an interface or class.
There is a maven plugin to check at compile-time that you are meeting the rules on immutability following this.
Hope this helps.