Is this class immutable or not? - java

The below class doesn't have final keyword but its member variables are private and final and the class exposes no mutate/set methods. Is this class immutable or not?
public class Abc {
private final int id;
private final String name;
public Abc(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}

The class itself is immutable, yes - if you create an instance of just Abc, no aspect of that can be changed after the instance has been created.
However, that doesn't mean that any code receiving a parameter of type Abc can assume it's immutable with all the benefits that carries... because the class isn't final. It's entirely possible for an object of a type compatible with Abc to be mutable:
public class Mutable extends Abc {
private String value;
public Mutable(int id, String name) {
super(id, name);
}
public void setValue(String value) {
this.value = value;
}
#Override public String toString() {
return value;
}
}
Now imagine you've got code which deals with an Abc:
public class AbcConsumer {
private final Abc abc;
public AbcConsumer(Abc abc) {
this.abc = abc;
}
// No need to create a defensive copy or anything like that...
// abc is immutable, right?
public Abc getAbc() {
return abc;
}
}
Here the consumer assumes it's fine to treat Abc as if it's an immutable class - but if someone creates an AbcConsumer by passing in a Mutable instance instead of "vanilla" Abc instance, it could cause problems.
That's why it's generally a good idea when you're creating an immutable type to make it final as well - that way any consumers know that if they receive a reference with that type, it's definitely immutable.
To put it another way: yes, the Abc class is immutable... but you can't assume that a reference with a compile-time type of Abc refers to an immutable object.

As presented, yes, the class is immutable.
The "final" keyword on a class declaration prevents it from being extended - it's not related to immutability (unless your variables are declared public or protected).
Edit; "not related" is a poor choice of words, please see Jon Skeet's answer below

No, it is most likely not.
A problem is terminology. What do you mean by class? If you mean this code, sure, it's immutable. But 'this code' is not something that is particularly relevant to the concept of immutability. That usually makes a lot more sense if we consider it: this type.
As in, is the type Abc immutable?
As in, given:
public void foo(Abc abc) { ... }
is it safe to assume that the received abc couldn't possibly change?
And then the answer is no. That is not safe to assume: The type Abc is mutable.
The reason is that someone could make this:
class SneakyAbc extends Abc {
private int id;
public void setId(int id) {
this.id = id;
}
public String getId() {
return id;
}
}
This is why immutable classes are virtually always made final, to fully guarantee it.
Depending on how fancy you want to paint with the brush of 'what does this term mean', if all methods of Abc are final, you can consider it immutable as well if you really want to: Whilst the class does not need to be immutable (a subclass can add a new non-final field and create getters and setters for this), all the stuff you can 'witness' from the Abc type, assuming you don't use reflection, do appear immutable.
Exactly what definition of immutable you go with would be required knowledge to delve any further.
Note that something like java.io.File has only final fields and is final, and yet, it has easily observable state that can be modified: just.. delete the file, and voila you can see it. You can pull similar stunts with an IdentityHashMap to create a faux but nevertheless very observable 'field'.
Thus, 'immutable' as a concept: Useful. As a boolean flag to bestow upon a certain type or some java source file: Not useful.

Records
Other Answers directly addressed your questions about immutability, class being marked final, and subclasses being mutable. I’ll add an alternative option to more briefly accomplish your goal of immutability: Records.
Java 16 brings the new records feature. If the main purpose of your class is to immutably and transparently carry data, define your class as a record. The compiler implicitly creates default constructor, getters, equals & hashCode, and toString.
A record is implicitly final, so no risk of a subclass becoming mutable.
Declare the properties in parentheses. By default, you need not put anything in the curly braces body of a record.
record Abc ( int id , String name ) {}
Instantiate like any other class.
Abc x = new Abc ( 42 , "Snuffleupagus" ) ;
The implicit getter methods are simply the property names. The JavaBeans-style get…/is… method naming is not used. (You could add such methods if required.)
System.out.println( x.name() ) ;
Snuffleupagus

It is mutable if its internal states can be changed after the class is created.
In your example, although there is no class final, the inside situations cannot be changed again because of final keyword. In this way, the class becomes immutable again

Related

Why can't an immutable class have setter methods? [duplicate]

This question already has answers here:
What is meant by immutable?
(17 answers)
Closed 3 years ago.
I was reading about immutable classes, and the ways to make a class immutable were said to be:
1 - Make the class final to prevent inheritance
2 - Make the mutable variables final
3 - Don't provide setter methods.
I think the third condition is unnecessary. When we make a variable final and provide any value to it, after that new value can't be assigned to it even through a setter method (because final variables can't be changed once a value is assigned to it). So why do we need the third condition of not having setter methods?
Am I understanding something in a wrong way?
public class Person{
private String name;
public Person(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
Now, it is clear that Person is not an Immutable class. This doesn't mean, an instance of Person can't be a member of another class that is (supposedly) immutable.
public final class MyImmutableClass {
// p is final, so it can't be re-referenced
private final Person p;
public MyImmutableClass(Person p) {
this.p = p;
}
// it can be altered, though
public void setPersonName(String name) {
this.p.setName(name);
}
public String toString() {
return "Person: " + p.getName();
}
}
Now, we have an immutable class, but, it does contain a setter. This setter actively changes a member of the (final) field p.
public static void main(String[] args) {
MyImmutableClass c = new MyImmutableClass(new Person("OriginalName"));
System.out.println(c);
c.setPersonName("AlteredName");
System.out.println(c);
}
And .. there you have it. The member is changed, through the setter (even though the variable was final). Do understand, a 'final variable' is NOT necessarily a constant, in most cases it's state can be changed. The point of a final variable, is that it can not be re-referenced. Note, we could also have a method like this:
public void setPerson(Person p) {
this.p.setName(p.getName());
}
A final variable itself is only a constant in case the type itself is an immutable type, or if it's a primitive, but you should understand that most types out there are mutable.
Is the type immutable or a primitive and it's declared final? Sure, add a setter. But, to what end? Misleading people who use your class?
You are sort of right. A setter, by definition, replaces a field with the given value. If all of the fields are final then you couldn't possibly provide a setter anyway.
My description of how to write an immutable class would be:
Make all fields final
Make sure the type of every field is itself immutable
It's possible to write an immutable class with fields that are mutable if you take great care to ensure that they never change but you need to be very careful in this case.
Yes, it could be reduced to
Make the class final to prevent inheritance;
Make the mutable variables final, and so don't bother providing any setters;
However for education purposes the shorter bullet points probably work better - even if slightly redundant.
The variable mentioned in item 2 can be a reference, which can be mutable (like a list or set) even when the variable itself is final.
This is why we have utilities like Collections.unmodifiableList to make mutable classes virtually immutable.
So the prohibition on setters is to prevent accidentally changing a final variable's state.
Making fields final is not sufficient (or even required) to guarantee immutability. You need to make defensive copies of mutable objects within the immutable class.
class Foo {
private String str;
public Foo(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
The above class is immutable because:
String is immutable.
The field 'str' is private and can't be altered.
Now considering the following MyDate class.
public class MyDate {
private Date; // date is not immutable
public MyDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
The MyDate class above is not immutable because the user can do the following:
Date d = new Date(<someDate>);
MyDate md = new MyDate(d);
d.set(<someDate>); // oops, just changed value in MyDate via external reference.
The same could also be done via getDate().
To make MyClass immutable, make defensive copies of Date in the constructor and getter. These prevent the user of the class from changing the date field either:
Using a reference to the constructor argument.
Upon retrieving the date field via a getter
public class MyDate {
private Date; // date is not immutable
public MyDate(Date date) {
this.date = new Date(date);
}
public Date getDate() {
return new Date(date);
}
}

Is My java class Immutable

Please see i am not asking what is immutability, i understand immutability but question is more how to make an immutable class when you are giving reference to a mutable object. Moreover my class failed the check with mutability detector project, hence requesting your view.
I have created a Immutable class EmpAndAddress.java and it has reference to a mutable class EmpAddress.java which is cloneable.
I have followed the java rules and tried to test my class using mutability detector but my class is failing the immutable test. Just want to check if I am missing something. In my Immutable i am always creating new Object of type EmpAddress mutable to follow the rules.
http://mutabilitydetector.github.io/MutabilityDetector/
1. Mutable EmpAddress.java
public class EmpAddress implements Cloneable{
public String empCity;
public int zipCode;
public EmpAddress(String empCity, int zipCode) {
super();
this.empCity = empCity;
this.zipCode = zipCode;
}
public String getEmpCity() {
return empCity;
}
public void setEmpCity(String empCity) {
this.empCity = empCity;
}
public int getZipCode() {
return zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
protected Object clone() throws CloneNotSupportedException {
EmpAddress clone=(EmpAddress)super.clone();
return clone;
}
}
public final class EmpAndAddress implements Cloneable {
private final int empId;
private final String empName;
private final EmpAddress eAddr;
public EmpAndAddress(int empId,String empName,EmpAddress eAddr){
super();
this.empId = empId;
this.empName = empName;
this.eAddr = new EmpAddress(" ", -1);
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
public EmpAddress geteAddr() throws CloneNotSupportedException {
return (EmpAddress) eAddr.clone();
}
}
The only problem I see is that you are actually not using the EmpAddress instance being passed to the EmpAndAddress constructor. I doubt that was intentional on your part.
In any case, to ensure that your class is immutable despite a reference to a mutable object is by performing clones both when receiving the EmpAddress instance in the constructor, and when returning an instance from the geteAddr() method.
You are already doing that inside the geteAddr() method, so you're ok on that front.
All that you are missing is fixing your constructor, like this:
public EmpAndAddress(int empId,String empName,EmpAddress eAddr){
this.empId = empId;
this.empName = empName;
this.eAddr = (EmpAddress) eAddr.clone();
}
The MutabilityDetector code is checking that the class is transitively immutable. It is not sufficient for the class itself to be immutable. The types of all of the classes fields must also be immutable. The child objects referenced by the fields are assumed to be part of the state of the parent object, so changing a child object changes the parent.
In your case, the (supposedly) immutable class EmpAndAddress has a field whose type is mutable. Furthermore, the field in an EmpAndAddress object is initialized with a value that is passed as a constructor argument. If the caller of the constructor keeps the EmpAddress reference, it can change the state of the EmpAndAddress object.
Full disclosure: author of Mutability Detector here... with a loooong answer.
If we start out with the class you defined in your question, and assert on it being immutable, like so;
#Test
public void isImmutable() {
assertImmutable(EmpAndAddress.class);
}
You get a test failure with the following message:
org.mutabilitydetector.unittesting.MutabilityAssertionError:
Expected: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress to be IMMUTABLE
but: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress is actually NOT_IMMUTABLE
Reasons:
Field can have a mutable type (org.mutabilitydetector.stackoverflow.Question_32020847$EmpAddress) assigned to it. [Field: eAddr, Class: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress]
Allowed reasons:
None.
(I've defined both classes as a static inner class, hence showing up as $EmpAndAddress in the message, but ignore that for now.)
Another answer to this question is totally correct. EmpAndAddress is considered mutable because EmpAddress is considered mutable, and every field of an immutable object should also be immutable. EmpAddress is mutable for several reasons: can be subclassed; has public non-final fields; setter methods. The first question is, why does cloning the EmpAddress field in the getter not help make it immutable? Well, in this case it does happen to make it immutable, but Mutability Detector doesn't perform the kind of analysis required to be confident of it. Mutability Detector doesn't have any special analysis for safely cloning mutable objects when letting them "escape" to callers. This is because it's very easy to misuse .clone and introduce mutability. Imagine if EmpAddress had a mutable field, like List, you can observe mutation like so:
#Test
public void go_on_try_to_mutate_me_now_i_have_a_list_field() throws Exception {
EmpAndAddress e = new EmpAndAddress(1234, "John Doe");
assertThat(e.geteAddr().getMyList(), is(Collections.<String>emptyList()));
e.geteAddr().getMyList().add("Haha, I'm mutating you");
assertThat(e.geteAddr().getMyList(), is(Collections.<String>emptyList())); // Fails because list now has one element in it
}
This is because Object.clone does not perform deep copies. It's only safe in this case because the fields cloned in EmpAddress are immutable (String and primitive int). Mutability Detector could try to recognise safe usages of .clone, but it would probably be very fragile. Because it can't be confident that your class is immutable, Mutability Detector decides it is mutable.
You are correct that creating a new Object of type EmpAddress is helping to make the class immutable, that's because it is "protecting" the instance, keeping it private, where no other code can access it. If the constructor took an instance and assigned it to a field, whoever passed the parameter to the constructor could modify it, thus mutating any instance that used it for a field. Like in this example:
#Test
public void mutate_object_by_giving_it_a_parameter_then_modifying_it() throws Exception {
EmpAddress empAddress = new EmpAddress("New York", 1234);
EmpAndAddress e = new EmpAndAddress(1234, "John Doe", empAddress);
assertThat(e.geteAddr().getCity, is("New York"));
empAddress.setCity("Haha, I'm mutating you");
assertThat(e.geteAddr().getCity(), is("New York")); // fails because city has been changed
}
So, what to do about it? There are a couple of options.
Method 1: Override Mutability Detector because you know better
Change your test to add an "allowed reason" to be mutable. That is, you are satisfied the failure is a false positive, you want to catch other potential errors which introduce mutability, but ignore this case. To do this, add code like the following:
#Test
public void isImmutable_withAllowedReason() {
assertInstancesOf(EmpAndAddress.class, areImmutable(),
AllowedReason.assumingFields("eAddr").areNotModifiedAndDoNotEscape());
}
You should be very sure about this before you take this option, and if you are new to immutable objects, I would recommend not doing this, so that you can learn to create immutable objects more safely.
Method 2: Make EmpAddress immutable as well, like so:
#Immutable
public static final class ImmutableEmpAddress {
private final String empCity;
private final int zipCode;
public ImmutableEmpAddress(String empCity, int zipCode) {
this.empCity = empCity;
this.zipCode = zipCode;
}
public String getEmpCity() { return empCity; }
public int getZipCode() { return zipCode; }
}
Then when you return it as a field from EmpAndAddress you don't need to clone it. This would be an ideal solution.
Method 3: Create an immutable adapter
However, in some cases you can't make EmpAddress immutable. Maybe the code is in a different library, or it's used by a framework that needs to set fields on it with reflection (such as Hibernate, or other JavaBean libraries). In this case you could create an immutable adapter like so:
#Immutable
public static final class ImmutableEmpAddressAdapter {
public final String empCity;
public final int zipCode;
public ImmutableEmpAddressAdapter(EmpAddress mutableAddress) {
// perform a deep copy of every field on EmpAddress that's required to re-construct another instance
this.empCity = mutableAddress.getEmpCity();
this.zipCode = mutableAddress.getZipCode();
}
public EmpAddress getEmpAddress() {
return new EmpAddress(this.empCity, this.zipCode);
}
}
Then in EmpAndAddress could look like this:
public static final class EmpAndAddress {
// some code ommitted for brevity
private final ImmutableEmpAddressAdapter immutableEmpAddressAdapter;
public EmpAndAddress(int empId, String empName){
this.immutableEmpAddressAdapter = new ImmutableEmpAddressAdapter(new EmpAddress(" ", -1));
}
public EmpAddress geteAddr() {
return immutableEmpAddressAdapter.getEmpAddress();
}
}
Although this technique would require more code, it makes it very explicit to other readers of this class that EmpAddress has an immutable field, and doesn't rely on fragile behaviour of Object.clone
This is also a good technique if you want to make a class immutable, but you have to make many code changes to do it. This allows you to gradually introduce an immutable version in more and more places in a codebase until eventually the original mutable class is only used at the margins of your system, or even disappears entirely.
I hope this anwser, and Mutability Detector have been useful in learning how to create immutable objects.

Immutability property in java

I know that when it comes to passing objects in java, the reference of object is passed as value. So what ever changes you make to that object is reflected in the original object as well. To avoid this we make use of immutability property in java.
So my question is, I have created an immutable class Employee, When I pass an object of this Employee class to some method in other class, I don't want that method to make any changes to this object. Even if it does, I don't want the changes to be affected to the original object created in the calling class.
Here is my sample code.
public final class Employee {
int employeeId;
public int getId() {
return employeeId;
}
public void setId(int id) {
this.employeeId = id;
}
}
public class Worker {
public static void process(Employee f, Employee g){
int c = f.getId();
f.setId(g.getId());
g.setId(c);
}
}
public class ImmutabilityTest{
public static void main(String[] args) {
Employee teamMember = new Employee();
Employee teamLead = new Employee();
teamMember.setId(5);
teamLead.setId(10);
System.out.println("Before process "+teamMember.getId() + " " + teamLead.getId());
Worker.process(teamMember, teamLead);
System.out.println("After process "+teamMember.getId() + " " + teamLead.getId());
}
}
The output will be
Before process 5 10
After process 10 5
Is there any way to avoid the change in the values of the member variables of the Employee class ? (apart from making them final)If not then how are we actually exploiting the Immutability property in java in user defined class ?
Any suggestions/opinions/pointers are appreciated ! Thanks..
Immutability is not a property in Java that can be applied to an Object with a single keyword, its a strategy that needs to be implemented on a case by case basis. Generally speaking, you utilize the final keyword and cloning in order to accomplish this. Note that the deeper your object nesting, the greater the level of difficulty in achieving true object immutability.
Here is a (more) immutable version of your Employee class:
public class Employee {
final int employeeId;
public Employee(final int id) {
super();
this.employeeId = id;
}
public int getId() {
return employeeId;
}
}
Note that reflection in Java makes it practically impossible to achieve true immutability, even with the use of the final instance variables and cloning.
Employee has a setter and has a non-private field, therefore it is not immutable.
Remove the setter, and make the field private, and your problem is solved.
Your other option is to pass a copy of the object (typically using a copy constructor to create it)
Applying the final keyword to a class simply indicates that the class can not be extended (or sub-classed).
It has nothing to do with whether or not its members can be modified.
You could change the visibility of the setId method to be package private, and make sure that Worker is in a different package to Employee.
Alternatively remove the setId method entirely.
[If the other class makes changes] I don't want the changes to be affected to the original object created in the calling class.
If you want to take that approach, then you need to create and pass a copy of the original object.
Note that unless you declare the private employeeId field to be final, you won't get the full benefit of immutability. Strictly speaking, the getId method needs to be synchronized if there is any possibility that different threads will call getId on the same Employee instance.
If you Don't want someone to change your properties value, you can keep them as private without setter.

How to create immutable objects in Java?

How to create immutable objects in Java?
Which objects should be called immutable?
If I have class with all static members is it immutable?
Below are the hard requirements of an immutable object.
Make the class final
make all members final, set them
explicitly, in a static block, or in the constructor
Make all members private
No Methods that modify state
Be extremely careful to limit access to mutable members(remember the field may be final but the object can still be mutable. ie private final Date imStillMutable). You should make defensive copies in these cases.
The reasoning behind making the class final is very subtle and often overlooked. If its not final people can freely extend your class, override public or protected behavior, add mutable properties, then supply their subclass as a substitute. By declaring the class final you can ensure this won't happen.
To see the problem in action consider the example below:
public class MyApp{
/**
* #param args
*/
public static void main(String[] args){
System.out.println("Hello World!");
OhNoMutable mutable = new OhNoMutable(1, 2);
ImSoImmutable immutable = mutable;
/*
* Ahhhh Prints out 3 just like I always wanted
* and I can rely on this super immutable class
* never changing. So its thread safe and perfect
*/
System.out.println(immutable.add());
/* Some sneak programmer changes a mutable field on the subclass */
mutable.field3=4;
/*
* Ahhh let me just print my immutable
* reference again because I can trust it
* so much.
*
*/
System.out.println(immutable.add());
/* Why is this buggy piece of crap printing 7 and not 3
It couldn't have changed its IMMUTABLE!!!!
*/
}
}
/* This class adheres to all the principles of
* good immutable classes. All the members are private final
* the add() method doesn't modify any state. This class is
* just a thing of beauty. Its only missing one thing
* I didn't declare the class final. Let the chaos ensue
*/
public class ImSoImmutable{
private final int field1;
private final int field2;
public ImSoImmutable(int field1, int field2){
this.field1 = field1;
this.field2 = field2;
}
public int add(){
return field1+field2;
}
}
/*
This class is the problem. The problem is the
overridden method add(). Because it uses a mutable
member it means that I can't guarantee that all instances
of ImSoImmutable are actually immutable.
*/
public class OhNoMutable extends ImSoImmutable{
public int field3 = 0;
public OhNoMutable(int field1, int field2){
super(field1, field2);
}
public int add(){
return super.add()+field3;
}
}
In practice it is very common to encounter the above problem in Dependency Injection environments. You are not explicitly instantiating things and the super class reference you are given may actually be a subclass.
The take away is that to make hard guarantees about immutability you have to mark the class as final. This is covered in depth in Joshua Bloch's Effective Java and referenced explicitly in the specification for the Java memory model.
Just don't add public mutator (setter) methods to the class.
Classes are not immutable, objects are.
Immutable means: my public visible state cannot change after initialization.
Fields do not have to be declared final, though it can help tremendously to ensure thread safety
If you class has only static members, then objects of this class are immutable, because you cannot change the state of that object ( you probably cannot create it either :) )
To make a class immutable in Java , you can keep note of the following points :
1. Do not provide setter methods to modify values of any of the instance variables of the class.
2. Declare the class as 'final' . This would prevent any other class from extending it and hence from overriding any method from it which could modify instance variable values.
3. Declare the instance variables as private and final.
4. You can also declare the constructor of the class as private and add a factory method to create an instance of the class when required.
These points should help!!
From oracle site, how to create immutable objects in Java.
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:
I. Don't provide methods that modify the mutable objects.
II. 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.
An immutable object is an object that will not change its internal state after creation. They are very useful in multithreaded applications because they can be shared between threads without synchronization.
To create an immutable object you need to follow some simple rules:
1. Don't add any setter method
If you are building an immutable object its internal state will never change. Task of a setter method is to change the internal value of a field, so you can't add it.
2. Declare all fields final and private
A private field is not visible from outside the class so no manual changes can't be applied to it.
Declaring a field final will guarantee that if it references a primitive value the value will never change if it references an object the reference can't be changed. This is not enough to ensure that an object with only private final fields is not mutable.
3. If a field is a mutable object create defensive copies of it for
getter methods
We have seen before that defining a field final and private is not enough because it is possible to change its internal state. To solve this problem we need to create a defensive copy of that field and return that field every time it is requested.
4. If a mutable object passed to the constructor must be assigned to a
field create a defensive copy of it
The same problem happens if you hold a reference passed to the constructor because it is possible to change it. So holding a reference to an object passed to the constructor can create mutable objects. To solve this problem it is necessary to create a defensive copy of the parameter if they are mutable objects.
Note that if a field is a reference to an immutable object is not necessary to create defensive copies of it in the constructor and in the getter methods it is enough to define the field as final and private.
5. Don't allow subclasses to override methods
If a subclass override a method it can return the original value of a mutable field instead of a defensive copy of it.
To solve this problem it is possible to do one of the following:
Declare the immutable class as final so it can't be extended
Declare all methods of the immutable class final so they can't be overriden
Create a private constructor and a factory to create instances of the immutable class because a class with private constructors can't be extended
If you follow those simple rules you can freely share your immutable objects between threads because they are thread safe!
Below are few notable points:
Immutable objects do indeed make life simpler in many cases. They are especially applicable for value types, where objects don't have an identity so they can be easily replaced and they can make concurrent programming way safer and cleaner (most of the notoriously hard to find concurrency bugs are ultimately caused by mutable state shared between threads).
However, for large and/or complex objects, creating a new copy of the object for every single change can be very costly and/or tedious. And for objects with a distinct identity, changing an existing objects is much more simple and intuitive than creating a new, modified copy of it.
There are some things you simply can't do with immutable objects, like have bidirectional relationships. Once you set an association value on one object, it's identity changes. So, you set the new value on the other object and it changes as well. The problem is the first object's reference is no longer valid, because a new instance has been created to represent the object with the reference. Continuing this would just result in infinite regressions.
To implement a binary search tree, you have to return a new tree every time: Your new tree will have had to make a copy of each node that has been modified (the un-modified branches are shared). For your insert function this isn't too bad, but for me, things got fairly inefficient quickly when I started to work on delete and re-balance.
Hibernate and JPA essentially dictate that your system uses mutable objects, because the whole premise of them is that they detect and save changes to your data objects.
Depending on the language a compiler can make a bunch of optimizations when dealing with immutable data because it knows the data will never change. All sorts of stuff is skipped over, which gives you tremendous performance benefits.
If you look at other known JVM languages (Scala, Clojure), mutable objects are seen rarely in the code and that's why people start using them in scenarios where single threading is not enough.
There's no right or wrong, it just depends what you prefer. It just depends on your preference, and on what you want to achieve (and being able to easily use both approaches without alienating die-hard fans of one side or another is a holy grail some languages are seeking after).
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.
First of all, you know why you need to create immutable object, and what are the advantages of immutable object.
Advantages of an Immutable object
Concurrency and multithreading
It automatically Thread-safe so synchronization issue....etc
Don't need to copy constructor
Don't need to implementation of clone.
Class cannot be override
Make the field as a private and final
Force callers to construct an object completely in a single step, instead of using a no-Argument constructor
Immutable objects are simply objects whose state means object's data can't change after the
immutable object are constructed.
please see the below code.
public final class ImmutableReminder{
private final Date remindingDate;
public ImmutableReminder (Date remindingDate) {
if(remindingDate.getTime() < System.currentTimeMillis()){
throw new IllegalArgumentException("Can not set reminder" +
" for past time: " + remindingDate);
}
this.remindingDate = new Date(remindingDate.getTime());
}
public Date getRemindingDate() {
return (Date) remindingDate.clone();
}
}
Minimize mutability
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is provided when it is created and is fixed for the lifetime of the object.
JDK immutable classes: String, the boxed primitive classes(wrapper classes), BigInteger and BigDecimal etc.
How to make a class immutable?
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended.
Make all fields final.
Make all fields private.
This prevents clients from obtaining access to mutable objects referred to by fields and modifying these objects directly.
Make defensive copies.
Ensure exclusive access to any mutable components.
public List getList() {
return Collections.unmodifiableList(list); <=== defensive copy of the mutable
field before returning it to caller
}
If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference or return the object reference from an accessor.
import java.util.Date;
public final class ImmutableClass {
public ImmutableClass(int id, String name, Date doj) {
this.id = id;
this.name = name;
this.doj = doj;
}
private final int id;
private final String name;
private final Date doj;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* Date class is mutable so we need a little care here.
* We should not return the reference of original instance variable.
* Instead a new Date object, with content copied to it, should be returned.
* */
public Date getDoj() {
return new Date(doj.getTime()); // For mutable fields
}
}
import java.util.Date;
public class TestImmutable {
public static void main(String[] args) {
String name = "raj";
int id = 1;
Date doj = new Date();
ImmutableClass class1 = new ImmutableClass(id, name, doj);
ImmutableClass class2 = new ImmutableClass(id, name, doj);
// every time will get a new reference for same object. Modification in reference will not affect the immutability because it is temporary reference.
Date date = class1.getDoj();
date.setTime(date.getTime()+122435);
System.out.println(class1.getDoj()==class2.getDoj());
}
}
For more information, see my blog:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html
an object is called immutable if its state can not be changed once created. One of the most simple way of creating immutable class in Java is by setting all of it’s fields are final.If you need to write immutable class which includes mutable classes like "java.util.Date". In order to preserve immutability in such cases, its advised to return copy of original object,
Immutable Objects are those objects whose state can not be changed once they are created, for example the String class is an immutable class. Immutable objects can not be modified so they are also thread safe in concurrent execution.
Features of immutable classes:
simple to construct
automatically thread safe
good candidate for Map keys and Set as their internal state would not change while processing
don't need implementation of clone as they always represent same state
Keys to write immutable class:
make sure class can not be overridden
make all member variable private & final
do not give their setter methods
object reference should not be leaked during construction phase
The following few steps must be considered, when you want any class as an immutable class.
Class should be marked as final
All fields must be private and final
Replace setters with constructor(for assigning a value to a
variable).
Lets have a glance what we have typed above:
//ImmutableClass
package younus.attari;
public final class ImmutableExample {
private final String name;
private final String address;
public ImmutableExample(String name,String address){
this.name=name;
this.address=address;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
//MainClass from where an ImmutableClass will be called
package younus.attari;
public class MainClass {
public static void main(String[] args) {
ImmutableExample example=new ImmutableExample("Muhammed", "Hyderabad");
System.out.println(example.getName());
}
}
Commonly ignored but important properties on immutable objects
Adding over to the answer provided by #nsfyn55, the following aspects also need to be considered for object immutability, which are of prime importance
Consider the following classes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = mc;
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class MutabilityCheck {
public static void main(String[] args) {
MutableClass mc = new MutableClass();
mc.setName("Foo");
ImmutableClass iMC = new ImmutableClass(mc);
System.out.println(iMC.getMutClass().getName());
mc.setName("Bar");
System.out.println(iMC.getMutClass().getName());
}
}
Following will be the output from MutabilityCheck :
Foo
Bar
It is important to note that,
Constructing mutable objects on an immutable object ( through the constructor ), either by 'copying' or 'cloing' to instance variables of the immutable described by the following changes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = new MutableClass(mc);
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public MutableClass() {
}
//copy constructor
public MutableClass(MutableClass mc) {
this.name = mc.getName();
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
still does not ensure complete immutability since the following is still valid from the class MutabilityCheck:
iMC.getMutClass().setName("Blaa");
However, running MutabilityCheck with the changes made in 1. will result in the output being:
Foo
Foo
In order to achieve complete immutability on an object, all its dependent objects must also be immutable
From JDK 14+ which has JEP 359, we can use "records". It is the simplest and hustle free way of creating Immutable class.
A record class is a shallowly immutable, transparent carrier for a fixed set of fields known as the record components that provides a state description for the record. Each component gives rise to a final field that holds the provided value and an accessor method to retrieve the value. The field name and the accessor name match the name of the component.
Let consider the example of creating an immutable rectangle
record Rectangle(double length, double width) {}
No need to declare any constructor, no need to implement equals & hashCode methods. Just any Records need a name and a state description.
var rectangle = new Rectangle(7.1, 8.9);
System.out.print(rectangle.length()); // prints 7.1
If you want to validate the value during object creation, we have to explicitly declare the constructor.
public Rectangle {
if (length <= 0.0) {
throw new IllegalArgumentException();
}
}
The record's body may declare static methods, static fields, static initializers, constructors, instance methods, and nested types.
Instance Methods
record Rectangle(double length, double width) {
public double area() {
return this.length * this.width;
}
}
static fields, methods
Since state should be part of the components we cannot add instance fields to records. But, we can add static fields and methods:
record Rectangle(double length, double width) {
static double aStaticField;
static void aStaticMethod() {
System.out.println("Hello Static");
}
}

What would be the best way to implement a constant object?

First of all I should probably say that the term 'constant object' is probably not quite right and might already mean something completely different from what I am thinking of, but it is the best term I can think of to describe what I am talking about.
So basically I am designing an application and I have come across something that seems like there is probably an existing design pattern for but I don't know what it is or what to search for, so I am going to describe what it is I am trying to do and I am looking for suggestions as to the best way to implement it.
Lets say you have a class:
public class MyClass {
private String name;
private String description;
private int value;
public MyClass(String name, String description, int value) {
this.name = name;
this.description = description;
this.value = value;
}
// And I guess some getters and setters here.
}
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
At first I thought that I should declare some static constants somewhere, e.g.
public static final String INSTANCE_1_DATA_FILE = "path/to/instance1/file";
public static final String INSTANCE_2_DATA_FILE = "path/to/instance2/file";
public static final String INSTANCE_3_DATA_FILE = "path/to/instance3/file";
public static final MyClass INSTANCE_1 = new MyClass(getNameFromFile(INSTANCE_1_DATA_FILE), getDescriptionFromFile(INSTANCE_1_DATA_FILE), getValueFromFile(INSTANCE_1_DATA_FILE));
public static final MyClass INSTANCE_2 = new MyClass(getNameFromFile(INSTANCE_2_DATA_FILE), getDescriptionFromFile(INSTANCE_2_DATA_FILE), getValueFromFile(INSTANCE_2_DATA_FILE));
public static final MyClass INSTANCE_3 = new MyClass(getNameFromFile(INSTANCE_3_DATA_FILE), getDescriptionFromFile(INSTANCE_3_DATA_FILE), getValueFromFile(INSTANCE_3_DATA_FILE));
Obvisouly now, whenever I want to use one of the 3 instances I can just refer directly to the constants.
But I started thinking that there might be a cleaner way to handle this and the next thing I thought about was doing something like:
public MyClassInstance1 extends MyClass {
private static final String FILE_NAME = "path/to/instance1/file";
public String getName() {
if (name == null) {
name = getNameFromFile(FILE_NAME);
}
return name;
}
// etc.
}
Now whenever I want to use the instances of MyClass I can just use the one I want e.g.
private MyClass myInstance = new MyClassInstance2();
Or probably even better would be to make them singletons and just do:
private MyClass myInstance = MyClassInstance3.getInstance();
But I can't help but think that this is also not the right way to handle this situation. Am I overthinking the problem? Should I just have a switch statement somewhere e.g.
public class MyClass {
public enum Instance { ONE, TWO, THREE }
public static String getName(Instance instance) {
switch(instance) {
case ONE:
return getNameFromFile(INSTANCE_1_DATA_FILE);
break;
case TWO:
etc.
}
}
}
Can anyone tell me the best way to implement this? Note that I have written the sample code in Java because that is my strongest language, but I will probably be implementing the application in C++, so at the moment I am more looking for language independent design patterns (or just for someone to tell me to go with one of the simple solutions I have already mentioned).
If you want the values to be constant, then you will not need setters, otherwise code can simply change the values in your constants, making them not very constant. In C++, you can just declare the instances const, although I'd still get rid of the setters, since someone could always cast away the const.
The pattern looks ok, although the fact that you are creating a new instance each time one is requested, is not usual for constants.
In java, you can create enums that are "smart" e.g.
public enum MyClass {
ONE(INSTANCE_1_DATA_FILE),
TWO(INSTANCE_2_DATA_FILE),
//etc...
private MyClass(String dataFile)
{
this(getNameFromDataFile(dataFile), other values...)
}
private MyClass(String name, String data, etc...)
{
this.name = name;
// etc..
}
public String getName()
{
return name;
}
}
In C++, you would create your MyClass, with a private constructor that takes the filename and whatever else it needs to initialize, and create static const members in MyClass for each instance, with the values assigned a new instance of MyClass created using the private constructor.
EDIT: But now I see the scenario I don't think this is a good idea having static values. If the types of ActivityLevel are fundamental to your application, then you can enumerate the different type of activity level as constants, e.g. a java or string enum, but they are just placeholders. The actual ActivityDescription instances should come from a data access layer or provider of some kind.
e.g.
enum ActivityLevel { LOW, MED, HIGH }
class ActivityDescription
{
String name;
String otherDetails;
String description; // etc..
// perhaps also
// ActivityLevel activityLevel;
// constructor and getters
// this is an immutable value object
}
interface ActivityDescriptionProvider
{
ActivityDescription getDescription(ActivityLevel activityLevel);
}
You can implement the provider using statics if you want, or an enum of ActivityDescription instnaces, or better still a Map of ActivityLevel to ActivityDescription that you load from a file, fetch from spring config etc. The main point is that using an interface to fetch the actual description for a given ActivityLevel decouples your application code from the mechanics of how those descriptions are produced in the system. It also makes it possible to mock the implementation of the interface when testing the UI. You can stress the UI with a mock implementation in ways that is not possible with a fixed static data set.
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
I'd use an enum. And then rather in this flavor:
public enum MyEnum {
ONE("path/to/instance1/file"),
TWO("path/to/instance2/file"),
THREE("path/to/instance3/file");
private String name;
private MyEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Which can be used as follows:
MyEnum one = MyEnum.ONE;
String name = one.getName();
(I'm too slow once again, you already accepted an answer, but here it is anyway...)
You want to (a) prevent changes to the data held in objects of MyClass, and (b) allow only a fixed set of MyClass objects to exist, implying that runtime code should not be able to create new instances of MyClass.
Your initial example has a public constructor, which violates (b)
I'd use a Factory approach so the Factory is the only thing that can create instances, and the class doesn't provide any setters so it's immutable.
Depending on how much flexibility you want for the future, you could put the factory and the class in the same package and limit scope that way, or you could make MyClass an inner class within the factory. You may also consider making MyClass an interface separate from its implementation.
A properties file could be used to configure the factory itself.
The properties file (e.g. "foo.properties") could look something like
one=/path/to/datafile1
two=/another/path/to/datafile2
three=/path/to/datafile3
I use "Foo" instead of "MyClass" in the (Java) examples below.
public class FooFactory
{
/** A place to hold the only existing instances of the class */
private final Map<String, Foo> instances = new HashMap<String, Foo>();
/** Creates a factory to manufacture Foo objects */
// I'm using 'configFile' as the name of a properties file,
// but this could use a Properties object, or a File object.
public FooFactory(String configfile)
{
Properties p = new Properties();
InputStream in = this.getClass().getResourceAsStream();
p.load(in); // ignoring the fact that IOExceptions can be thrown
// Create all the objects as specified in the factory properties
for (String key : p.keys())
{
String datafile = p.getProperty(key);
Foo obj = new Foo(datafile);
instances.put(key, obj);
}
}
public Foo getFoo(String which)
{
return instances.get(which);
}
/** The objects handed out by the factory - your "MyClass" */
public class Foo
{
private String name;
private String description;
private int value;
private Foo(String datafile)
{
// read the datafile to set name, description, and value
}
}
}
You're set to allow only your predefined instances, which can't be changed at runtime, but you can set it all up differently for another run at a later time.
Your first method seems to me like the best and the least prone to code rot. I'm not impressed by the idea of subclassing an object just to change the file name that contains the data that will be used to build it.
Of course, you could maybe improve on your original idea by wrapping these all in an outer class that provides some sort of enumeration access. A collection of MyClass's in other words. But I think you should discard this subclassing idea.
First, you really should be limiting where you use these instances in the code. Use them in as few places as possible. Given these are file names, I expect you want three class instances which accesses the files. How many classes are required depends on what your want to do with them? Look at the Singleton pattern for these classes.
Now you don't need the constants, but could have a helper class which will read the file containing the file names and supply them to the reader class. The code to find then name could also be a method called by the static initializer of the Singleton.
The common approach is to use a map:
private static final Map<String, YouClass> mapIt =
new HashMap<String, YouClass>(){{
put("one", new YourClass("/name", "desc", 1 )),
put("two", new YourClass("/name/two", "desc2", 2 )),
put("three", new YourClass("/name/three", "desc", 3 ))
}}
public static YourClass getInstance( String named ) {
return mapIt.get( named );
}
Next time you need it:
YouClass toUse = YourClass.getInstance("one");
Probably using strings as keys is not the best option but you get the idea.

Categories