Make immutable Java object - java

My goal is to make a Java object immutable. I have a class Student. I coded it in the following way to achieve immutability:
public final class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
My question is, what is the best way to achieve immutability for the Student class?

Your class is not immutable strictly speaking, it is only effectively immutable. To make it immutable, you need to use final:
private final String name;
private final String age;
Although the difference might seem subtle, it can make a significant difference in a multi-threaded context. An immutable class is inherently thread-safe, an effectively immutable class is thread safe only if it is safely published.

There are few things that you must consider for making an immutable class:
Make your class final - You already have
Make all the fields private and final - Make appropriate changes in your code
Don't provide any methods that change the state of your instance
If you have mutable fields in your class, like List, or Date, making them final won't suffice. You should return a defensive copy from their getters, so that their state isn't mutated by calling methods.
For the 4th point, say you have a Date field in your class, then the getter for that field should look like:
public Date getDate() {
return new Date(this.date.getTime());
}
Making a defensive copy can become a headache, when your mutable field itself comprises of some mutable field, and that in turn can contain some other mutable field. In that case, you would need to make copy of each of them iteratively. We name this iterative copy of mutable fields as Deep Copy.
Implementing deep copy by yourself may be cumbersome. But,keeping that issue apart, you should consider your class design again, once you see yourself falling into such requirement of making deep defensive copy.

How do you make a mutable object immutable?
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.
source
Why do we create immutable objects?
Immutable objects are simply objects whose state (the object's data) cannot change after construction.
Security: store sensitive pieces of information like usernames, passwords, connection URLs, network connections etc.
are simple to construct, test, and use
are automatically thread-safe and have no synchronization issues
don't need a copy constructor
don't need an implementation of clone
allow hashCode to use lazy initialization, and to cache its return value
don't need to be copied defensively when used as a field
make good Map keys and Set elements (these objects must not change state while in the collection)
have their class invariant established once upon construction, and it never needs to be checked again
always have "failure atomicity" (a term used by Joshua Bloch): if an immutable object throws an exception, it's never left in an undesirable or indeterminate state
Source
In Java, Strings are immutable, which provides, such as caching, security, easy reuse without replication, etc.
Source

With final keyword:
private final String name;
private final String age;

Making variables private and no setter methods will work for primitive data types. If my class has any collection of objects?
To making any class immutable with collection object?
Write your own collection object with extends collection class and follow the private variables and no setter methods. or return clone object of your collection object.
public final class Student {
private StudentList names;//Which is extended from arraylist
public Student() {
names = DAO.getNamesList()//Which will return All Student names from Database its upto you how you want to implement.
}
public StudentList getStudentList(){
return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
}
public Enumeration getStudentNamesIterator(
Enumeration e = Collections.enumeration(names);
return e;
}
public class StudentList extends ArrayList {
}

This is fine but I would make the fields final as well.
Also I would make the age an int or double rather than a String.

Expanding on the answer a bit.
final is not the same as Immutable but you can use final to make certain things immutable if you use it in certain ways.
Certain types are immutable, in that they represent unchanging values rather than objects of changeable state. Strings, numbers, etc are immutable. At the end, usually our objects boil down to data structures eventually referencing immutable values, but we change the data structures by assigning new values to the same field names.
So to make something truly immutable you need to make sure that final is used all the way down, until you reach every field reaching every value at the base of your composition tree. Otherwise something could change out from under your the object and it isn't really fully immutable.

Your example is already immutable object, because fields in Student class can only set on instance initialization.
To make object immutable, You must do these steps:
Don't use any methods, which can change fields of your class. For example don't use Setters.
Avoid to use public non-final fields. If your fields is public then you must declare them as final and initialize them in constructor or directly in the declaration line.

It is too late to answer but may be it help other peoples who have this question.
State of immutable object can not be modified after construction, any modification should result in new immutable object.
All fields of Immutable class should be final.
Object must be properly constructed i.e. object reference must not leak during construction process.
Object should be final in order to restrict sub-class for altering immutability of parent class.
I think this link help more
Read more: http://javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1

It already is immutable -- you can't change the contents once you initialize it, since you haven't made setters. You might add final keywords to the variables.

Making all variables as final and when setting some field, making it return the reference to the new Student object with the newly set value like in String.

You can just follow guidelines shown in this example (first result in google):
http://www.javapractices.com/topic/TopicAction.do?Id=29

Here are few rules, which helps to make a class immutable in Java :
1. State of immutable object can not be modified after construction, any modification should result in new immutable object.
2. All fields of Immutable class should be final.
3. Object must be properly constructed i.e. object reference must not leak during construction process.
4. Object should be final in order to restrict sub-class for altering immutability of parent class.
Example:
public final class Contacts {
private final String name;
private final String mobile;
public Contacts(String name, String mobile) {
this.name = name;
this.mobile = mobile;
}
public String getName(){
return name;
}
public String getMobile(){
return mobile;
}
}
Refer this link : http://javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html

According to Strategy for Defining Immutable Objects
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. 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:
a. Don't provide methods that modify the mutable objects.
b. 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.

Java SE 16
You can use JEP 395: Records feature, introduced as part of Java SE 16, to create an immutable class in a succinct manner.
If you have already gone through the above link, you must have figured out that you can do it simply as
record Student(String name, String age) { }
What you get in turn are:
A final class Student.
A canonical constructor whose signature is the same as the header, Student(String name, String age).
private final fields, name and age and their corresponding public accessor method with the same name and return type.
Automatically created equals, hashCode and toString methods.
Demo:
Student.java
record Student(String name, String age) { }
Main.java
class Main{
public static void main(String[] args) {
Student s1 = new Student("Bharat", "10 Years");
Student s2 = new Student("Arvind", "10 Years");
System.out.println(s1);
System.out.println(s1.equals(s2));
System.out.println(s1.age().equals(s2.age()));
}
}
Output:
Student[name=Bharat, age=10 Years]
false
true

Make the class or variable as final that's more than enough
Public final class constants
{
private final String name;
private final String mobile;
// code
}

Related

Immutability - Java, Final required if no setters [duplicate]

Must immutable objects have all properties be final?
I would say they don't. But I don't know whether I am right or not.
The main difference between an immutable object (all properties final) and an effectively immutable object (properties aren't final but can't be changed) is safe publication.
You can safely publish an immutable object in a multi threaded context without having to worry about adding synchronization, thanks to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
As a side note, it also enables to enforce immutability (if you try to mutate those fields in a future version of your class because you have forgotten it should be immutable, it won't compile).
Clarifications
Making all the fields of an object final does not make it immutable - you also need to make sure that (i) its state can't change (for example, if the object contains a final List, no mutating operations (add, remove...) must be done after construction) and (ii) you don't let this escape during construction
An effectively immutable object is thread safe once it has been safely published
Example of unsafe publication:
class EffectivelyImmutable {
static EffectivelyImmutable unsafe;
private int i;
public EffectivelyImmutable (int i) { this.i = i; }
public int get() { return i; }
}
// in some thread
EffectivelyImmutable.unsafe = new EffectivelyImmutable(1);
//in some other thread
if (EffectivelyImmutable.unsafe != null
&& EffectivelyImmutable.unsafe.get() != 1)
System.out.println("What???");
This program could in theory print What???. If i were final, that would not be a legal outcome.
You can easily guarantee immutability by encapsulation alone, so it's not necessary:
// This is trivially immutable.
public class Foo {
private String bar;
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
}
However, you also must guarantee it by encapsulation in some cases, so it's not sufficient:
public class Womble {
private final List<String> cabbages;
public Womble(List<String> cabbages) {
this.cabbages = cabbages;
}
public List<String> getCabbages() {
return cabbages;
}
}
// ...
Womble w = new Womble(...);
// This might count as mutation in your design. (Or it might not.)
w.getCabbages().add("cabbage");
It's not a bad idea to do so to catch some trivial errors, and to demonstrate your intent clearly, but "all fields are final" and "the class is immutable" are not equivalent statements.
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.
Immutable objects MUST not be modified in any way after their creation. final of course helps to achieve that. You guarantee that they will not ever be changed. BUT what if you have an array inside your object that is final? Of course the reference is not changable, but the elements are. Look here at almost the same question I gave also:
Link
Simply declaring an object as final does not make it inherently immutable. Take for example this class:
import java.util.Date;
/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*/
public final class Planet {
public Planet (double aMass, String aName, Date aDateOfDiscovery) {
fMass = aMass;
fName = aName;
//make a private copy of aDateOfDiscovery
//this is the only way to keep the fDateOfDiscovery
//field private, and shields this class from any changes that
//the caller may make to the original aDateOfDiscovery object
fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
}
/**
* Returns a primitive value.
*
* The caller can do whatever they want with the return value, without
* affecting the internals of this class. Why? Because this is a primitive
* value. The caller sees its "own" double that simply has the
* same value as fMass.
*/
public double getMass() {
return fMass;
}
/**
* Returns an immutable object.
*
* The caller gets a direct reference to the internal field. But this is not
* dangerous, since String is immutable and cannot be changed.
*/
public String getName() {
return fName;
}
// /**
// * Returns a mutable object - likely bad style.
// *
// * The caller gets a direct reference to the internal field. This is usually dangerous,
// * since the Date object state can be changed both by this class and its caller.
// * That is, this class is no longer in complete control of fDate.
// */
// public Date getDateOfDiscovery() {
// return fDateOfDiscovery;
// }
/**
* Returns a mutable object - good style.
*
* Returns a defensive copy of the field.
* The caller of this method can do anything they want with the
* returned Date object, without affecting the internals of this
* class in any way. Why? Because they do not have a reference to
* fDate. Rather, they are playing with a second Date that initially has the
* same data as fDate.
*/
public Date getDateOfDiscovery() {
return new Date(fDateOfDiscovery.getTime());
}
// PRIVATE //
/**
* Final primitive data is always immutable.
*/
private final double fMass;
/**
* An immutable object field. (String objects never change state.)
*/
private final String fName;
/**
* A mutable object field. In this case, the state of this mutable field
* is to be changed only by this class. (In other cases, it makes perfect
* sense to allow the state of a field to be changed outside the native
* class; this is the case when a field acts as a "pointer" to an object
* created elsewhere.)
*/
private final Date fDateOfDiscovery;
}
No.
For example, see the implementation of java.lang.String. Strings are immutable in Java, but the field hash is not final (it is lazily computed the first time hashCode is called and then cached). But this works because hash can take on only one nondefault value that is the same every time it is computed.
String class is Immutable but property hash is not final
Well it is possible but with some rules/restrictions and that is access to mutable properties/fields must provide same result every time we access it.
In String class hashcode actually calculated on the final array of characters which is not going to change if String has constructed. Therefore immutable class can contain mutable fields/properties but it has to make sure that access to field/property will produce the same result every time it is accessed.
To answer your question it is not mandatory to have all the fields final in a immutable class.
For further reading visit here [blog] : http://javaunturnedtopics.blogspot.in/2016/07/string-is-immutable-and-property-hash.html
Not necessary, you can achieve same functionality by making member as non-final but private and not modifying them except in constructor. Don't provide setter method for them and if it is a mutable object, then don't ever leak any reference for that member.
Remember making a reference variable final, only ensures that it will not be reassigned a different value, but you can still change individual properties of an object, pointed by that reference variable. This is one of the key points.

Simulating property changes with immutable objects

After searching I found these questions, but no answers to my specific question:
Undo/Redo with immutable objects
Why continue to use getters with immutable objects
How to write a test friendly immutable value class
Is it okay to expose the state of an immutable object
Here's the setup:
I've got an immutable class like so:
public class MyImmutableOb {
private final String name;
private final Collection<Integer> myNumbers;
public MyImmutableOb(String name) {
this.name = name;
myNumbers = new LinkedList<>();
}
public MyImmutableOb(String name, MyImmutableOb oldOb) {
this.name = name;
myNumbers = new LinkedList<>();
for (int i : oldOb.getNumbers()) myNumbers.add(i);
}
public Collection<Integer> getNumbers() {
return new LinkedList<>(myNumbers);
}
}
I have included a constructor like this, meant to allow simulating a name change on the object. The question is, does reproducing the Collection in this fashion break immutability?:
public MyImmutableOb(String name, MyImmutableOb oldOb) {
this.name = name;
myNumbers = new LinkedList<>();
for (int i : oldOb.getNumbers()) myNumbers.add(i);
}
I am having a tough time wrapping my head around this one.
As you have discovered, in order to make instances of your class immutable, you have to explicity write immutability into your class; object types (as opposed to primitive types) are mutable by nature. The collections classes in java.util are of course mutable. Java classes like String and the primitive boxing types Integer, Double, etc., are written to be immutable.
Your variable declaration
private final String name;
is immutable because it is declared final and because String objects are immutable.
Using the final keyword for a variable ensures that the variable can be assigned a value only once, therefore it is an excellent tool for designing an immutable class. However, it is not enough, because if the variable is assigned to a mutable object then the variables in that object can still be modified.
Your variable declaration
private final Collection<int> myNumbers;
does not guarantee immutability because, although myNumbers can be assigned only once, the collection assigned to it is still mutable.
The good news is, the Java Collections utility class provides lightweight wrappers to make your collections immutable. This will require a change to your first constructor
public MyImmutableOb(String name, int... numbers) {
this.name = name;
this.myNumbers = Collections.unmodifiableList(Arrays.asList(numbers));
}
so that myNumbers is now truly immutable. Note I've forsaken your usage of LinkedList, because there's no point in using that specialized List implementation when it's immutable within MyImmutableOb.
Thus your second constructor becomes
public MyImmutableOb(String name, MyImmutableOb oldOb) {
this.name = name;
this.myNumbers = oldOb.myNumbers;
}
because oldOb's myNumbers is already immutable, so there's no point in copying.
In closing, I realize you probably did want to be able to change the contents of myNumbers after construction of a MyImmutableOb. Obviously, making the class truly immutable implies that nothing can change in its instances after construction.

Usage of final in java

I was wondering what the difference is between
public final type attribute_name;
and
private type attribute_name;
public type getA_name() {
return attribute_name;
}
Basically I want to make an attribute read-only, so it can't change after it has been initialized.
Do I make it public final, or do I make it private, and only make it accesible through a get method (without a set method)?
When it's not final but private, the class itself is able to change the value.
A final field MUST be set before the constructor exits. Once set, the reference cannot be modified (the value cannot be reassigned). Emphasis on the cannot be reassigned. This means that while the reference cannot change, the value itself can change.
This is legal:
final List<Integer> list = new List<Integer>();
list.add(5); // the value of list changes, but the reference doesn't
This is not:
final List<Integer> list = new List<Integer>();
list = new List<Integer>(); // may seem sort of redundant but the compiler won't allow it nonetheless
A private variable with a only getter can be reassigned internally by the class that holds it (but it's not visible externally so it cannot be reassigned outside the class holding it). Also, outside the class the reference is inaccessible so the variable cannot be modified except by the class holding it.
A final variable cannot be reassigned anywhere, but if it's public, another class can still access the reference and change the value of whatever object it points to.
If you don't want the variable to be reassigned after initialization as you described, use both final and private.
Use final for something like this:
public class User {
private final long registrationTimeMillis;
public User(/* various parameters probably would be here */) {
registrationTimeMillis = System.currentTimeMillis();
}
public long getRegistrationTimeMillis() {
return registrationTimeMillis;
}
}
We don't expect that a user's registration time will change, so it makes sense to not allow it to change after construction.
Use private with no setter for something like this:
public class VendingController() {
private int drinksStocked = 0;
private int drinksDispensed = 0;
public void dispenseDrink() {
drinksDispensed++;
}
public void stockDrinks(int numberOfDrinks) {
drinksStocked = getDrinksRemaining() + numberOfDrinks;
drinksDispensed = 0;
}
public int getDrinksRemaining() {
return drinksStocked - drinksDispensed;
}
}
We don't want the value of drinksDispensed to change except when dispenseDrink() or stockDrinks(int numberOfDrinks) is called. It still needs to be able to be reassigned by it's own class when the vending machine is refilled though, so we shouldn't make it final
With respect to using public final, generally in Java that's only done for constants and that static keyword is also included since constants shouldn't be dependent on an instance.
An example of when it makes sense to use public static final
public class UnitConversions {
public static final double CENTIMETERS_PER_INCH = 2.54;
}
It could then be used in a method as follows
public double convertFromCentimetersToInches(double centimeters) {
return centimeters / UnitConversions.CENTIMETERS_PER_INCH;
}
Best of luck OP and happy coding.
More reading on final fields
This depends on some factors.
If this is a real constant that is known before and will never change, then use final. In Java final fields can be initialized in the constructor as well, so if your value is known at construction time then you can use final too.
If this value gets set (once, multiple times) during runtime then use private + getter.
The final modifier allows a field to be assigned only once - it cannot be changed after that and it has to be set at during object construction (that is, before the constructor returns).
If you want to make the field read-only, use the principles of information hiding: make it private and provide a public getter that returns the field (or a copy of it for non-primitive types).
You should use public final only for true constants. Even if your field is immutable because of final it is often a good idea to still make it private.
The correct way is to think in the future. What would help you achieve your goals? Maybe later you would also like to give that variable a value. If I were you, I'd do this by creatin a get method and keeping the variable private.
Full documentation for final keyword : http://en.wikipedia.org/wiki/Final_(Java)
Depends on where you want to access it from. Public variables can be accessed from any class within the project and package where private can only be accessed from the class where the variable is.
The 'final' operator makes it permanent and read-only.
Let's assume that type is a reference to an object, not a primitive type.
public final type attribute_name means that attribute_name cannot be reassigned to refer to something else. But attribute_name can be used to call a method that changes its state.
In private type attribute_name, only methods within the class can call methods on attribute_name.
So if you want it to remain constant, use approach (2). Limit the public methods to ones that ultimately call methods on attribute_name that don't modify its state.

Immutable Class how to tell

I understand that immutable means that it is an object that will not change state after it is instantiated. But in this line of code I dont see Final when the array values is declared.
Is this class immutable? Can anyone explain how to find out. Thanks
public class A {
private double[] values;
public double[] getValues(){
return values;
}
}
As other have written this object is considered to be mutable in its state. What it is immutable to is that you can not exchange the array it holds. But you can change the array's content (getValues()[0] = 10;).
To convert this to a immutable object you must use List instead of an array. With List you can use Collections' method unmodifiableList to convert a given list into a version you can savely expose to the outside. If the caller of getValues() uses add or remove on a unmodifiable list it will result into a UnsupportedOpertionException keeping your object save from being modified.
If you need to stick to arrays you need to provide a copy (System.arraycopy) or a clone (clone()) of the array.
Usually a object is considered to be immutable if you can not change its properties (including inherited properties from superclasses. This usually includes the properties values as well but this is a blurred definition.
For example if you have a class that holds a File instance which points to document file and this File instance can not be changed the class is considered to be immutable (the inforamtion it provides never changes) but the document it points to can be mutated and changed every time. So its a blurred line actually (remember in your example you can not change the array but the content of the array).
Yes the code pasted is not having any final keyword associated and has no immutable behavior.
Well i would like to bring forth some key guidelines related to writing immutable classes in java :
1.) Ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
2.) Make fields private and final
force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention)
3.) Do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
4.) If the class has any mutable object fields, then they must be defensively copied when they pass between the class and its caller
A a = new A();
a.getValues()[0] = 1.2;
This would work as long as values is not empty. You will however not be able to reassign values to a new array. That is: a.getValues() = new double[5]; will not work.
The class is not immutable, as I can change values, just not reassign it.
Here is a simple verification. the values are initialized to 1,2.
Using the getter and a reference, one is able to change the values inside the first item in the array after the object is created
public class A {
private double[] values;
public double[] getValues() {
return values;
}
public static void main(String[] args) {
A test = new A();
test.values= new double[]{1, 2};
double[] valuesref = test.getValues();
valuesref[0] = 10;
for (int i = 0; i < test.values.length; i++) {
System.out.println(test.values[i]);
}
}
}
This can be avoided if getValues() returns a copy of the array.

Must all properties of an immutable object be final?

Must immutable objects have all properties be final?
I would say they don't. But I don't know whether I am right or not.
The main difference between an immutable object (all properties final) and an effectively immutable object (properties aren't final but can't be changed) is safe publication.
You can safely publish an immutable object in a multi threaded context without having to worry about adding synchronization, thanks to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
As a side note, it also enables to enforce immutability (if you try to mutate those fields in a future version of your class because you have forgotten it should be immutable, it won't compile).
Clarifications
Making all the fields of an object final does not make it immutable - you also need to make sure that (i) its state can't change (for example, if the object contains a final List, no mutating operations (add, remove...) must be done after construction) and (ii) you don't let this escape during construction
An effectively immutable object is thread safe once it has been safely published
Example of unsafe publication:
class EffectivelyImmutable {
static EffectivelyImmutable unsafe;
private int i;
public EffectivelyImmutable (int i) { this.i = i; }
public int get() { return i; }
}
// in some thread
EffectivelyImmutable.unsafe = new EffectivelyImmutable(1);
//in some other thread
if (EffectivelyImmutable.unsafe != null
&& EffectivelyImmutable.unsafe.get() != 1)
System.out.println("What???");
This program could in theory print What???. If i were final, that would not be a legal outcome.
You can easily guarantee immutability by encapsulation alone, so it's not necessary:
// This is trivially immutable.
public class Foo {
private String bar;
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
}
However, you also must guarantee it by encapsulation in some cases, so it's not sufficient:
public class Womble {
private final List<String> cabbages;
public Womble(List<String> cabbages) {
this.cabbages = cabbages;
}
public List<String> getCabbages() {
return cabbages;
}
}
// ...
Womble w = new Womble(...);
// This might count as mutation in your design. (Or it might not.)
w.getCabbages().add("cabbage");
It's not a bad idea to do so to catch some trivial errors, and to demonstrate your intent clearly, but "all fields are final" and "the class is immutable" are not equivalent statements.
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.
Immutable objects MUST not be modified in any way after their creation. final of course helps to achieve that. You guarantee that they will not ever be changed. BUT what if you have an array inside your object that is final? Of course the reference is not changable, but the elements are. Look here at almost the same question I gave also:
Link
Simply declaring an object as final does not make it inherently immutable. Take for example this class:
import java.util.Date;
/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*/
public final class Planet {
public Planet (double aMass, String aName, Date aDateOfDiscovery) {
fMass = aMass;
fName = aName;
//make a private copy of aDateOfDiscovery
//this is the only way to keep the fDateOfDiscovery
//field private, and shields this class from any changes that
//the caller may make to the original aDateOfDiscovery object
fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
}
/**
* Returns a primitive value.
*
* The caller can do whatever they want with the return value, without
* affecting the internals of this class. Why? Because this is a primitive
* value. The caller sees its "own" double that simply has the
* same value as fMass.
*/
public double getMass() {
return fMass;
}
/**
* Returns an immutable object.
*
* The caller gets a direct reference to the internal field. But this is not
* dangerous, since String is immutable and cannot be changed.
*/
public String getName() {
return fName;
}
// /**
// * Returns a mutable object - likely bad style.
// *
// * The caller gets a direct reference to the internal field. This is usually dangerous,
// * since the Date object state can be changed both by this class and its caller.
// * That is, this class is no longer in complete control of fDate.
// */
// public Date getDateOfDiscovery() {
// return fDateOfDiscovery;
// }
/**
* Returns a mutable object - good style.
*
* Returns a defensive copy of the field.
* The caller of this method can do anything they want with the
* returned Date object, without affecting the internals of this
* class in any way. Why? Because they do not have a reference to
* fDate. Rather, they are playing with a second Date that initially has the
* same data as fDate.
*/
public Date getDateOfDiscovery() {
return new Date(fDateOfDiscovery.getTime());
}
// PRIVATE //
/**
* Final primitive data is always immutable.
*/
private final double fMass;
/**
* An immutable object field. (String objects never change state.)
*/
private final String fName;
/**
* A mutable object field. In this case, the state of this mutable field
* is to be changed only by this class. (In other cases, it makes perfect
* sense to allow the state of a field to be changed outside the native
* class; this is the case when a field acts as a "pointer" to an object
* created elsewhere.)
*/
private final Date fDateOfDiscovery;
}
No.
For example, see the implementation of java.lang.String. Strings are immutable in Java, but the field hash is not final (it is lazily computed the first time hashCode is called and then cached). But this works because hash can take on only one nondefault value that is the same every time it is computed.
String class is Immutable but property hash is not final
Well it is possible but with some rules/restrictions and that is access to mutable properties/fields must provide same result every time we access it.
In String class hashcode actually calculated on the final array of characters which is not going to change if String has constructed. Therefore immutable class can contain mutable fields/properties but it has to make sure that access to field/property will produce the same result every time it is accessed.
To answer your question it is not mandatory to have all the fields final in a immutable class.
For further reading visit here [blog] : http://javaunturnedtopics.blogspot.in/2016/07/string-is-immutable-and-property-hash.html
Not necessary, you can achieve same functionality by making member as non-final but private and not modifying them except in constructor. Don't provide setter method for them and if it is a mutable object, then don't ever leak any reference for that member.
Remember making a reference variable final, only ensures that it will not be reassigned a different value, but you can still change individual properties of an object, pointed by that reference variable. This is one of the key points.

Categories