Simulating property changes with immutable objects - java

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.

Related

Returning a reference to a mutable object value stored in one of the object's fields exposes the internal representation of the object

I'm getting this error when running checkstyle on my code for the following lines:
#Override
public String[] getDescriptions() {
return DESCRIPTIONS;
}
but DESCRIPTIONS IS NOT mutable. It's defined as:
private static final String[] DESCRIPTIONS = new String[NUM_COLUMNS];
static {
// In a loop assign values to the array.
for (int i = 0; i < NUM_COLUMNS; ++i) {
DESCRIPTIONS[i] = "Some value";
}
}
This is the complete error message:
"Returning a reference to a mutable object value stored in one
of the object's fields exposes the internal representation of
the object. If instances are accessed by untrusted code, and
unchecked changes to the mutable object would compromise security
or other important properties, you will need to do something
different. Returning a new copy of the object is better approach
in many situations."
Related Question: Link
Arrays and some collections are not immutable in the sense that their content still remains mutable.
Immutability in Java only concerns object's reference assignment, not its deep content.
Try this:
#Override
public String[] getDescriptions() {
return Arrays.copyOf(DESCRIPTIONS, DESCRIPTIONS.length);
}
BTW, caution to java naming convention.. : descriptions, not DESCRIPTIONS
The reference variable is final so you cannot assign another array to DESCRIPTIONS. However, the object itself is mutable (arrays are always mutable), final or not. If you return the reference, then you lose control over the contents your variable, violating encapsulation.
You would need either to return a copy of the array, or don't return the array at all, providing a method to get a specific element of the array instead, if that's good enough.

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.

Make immutable Java object

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
}

Java: is a final reference to an array of enums immutable?

I think that a final reference to an array of enums should be immutable.
The uniqueness and singularity of enums is enforced by the JVM, so I believe it is safe to say that they are immutable.
A final reference cannot be changed, so the reference is immutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
I have a list of enums that correspond to database columns. These column names and their associated data do not change, so ... I would like to have the list as a class variable like so:
static final List<MetaData<Client>> C_COLUMNS =
DataTables.CLIENTS.getTableColumnsAsEnums();
where CLIENTS is the DataTable enum for which a list of column enums is being generated. The method that does this follows:
public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() {
Class<? extends MetaData> cls = this.columnsEnumToken();
return new ArrayList(Arrays.<MetaData<T>>asList(cls.getEnumConstants())); }
Am I right? This ought to become part of a multi-threaded design, and so I am concerned about the way that making this critical list of static data would render by app very vulnerable ... if it actually were mutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
Yes. All arrays in Java are mutable, irrespective of how you declare the variable that holds the reference to the array.
If you want to avoid this "risk", then you must not expose the array; i.e. you need to declare it as private. You could then do one (or more) of the following:
Define a static method that will create and return a copy of the array. (Probably not the best option here ...)
Define a static get(int) method that returns the ith element of the array.
Wrap the array in a list (using Arrays.asList) and create an unmodifiable wrapper for it (using Collections.unmodifiableList).
If you want to get the public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() to return an immutable List you need to use Collections.unmodifiableList()
Also when you are using an unmodifiable list you don't have to worry about the internal array because the toArray method will return an copy of the internal array, not a reference to the internal array itself. This is true for all the Collections.
The REFERENCE is immutable, the content of that reference is not, that's just how things work.
So the following won't work
public enum TheEnum {
//......
}
final TheEnum[] arr = new TheEnum[5];
var = new TheEnum[6];
but this will work
public enum TheEnum {
OPTION_ONE;
//......
}
final TheEnum[] arr = new TheEnum[5];
var[1] = TheEnum.OPTION_ONE;

Can a class (an instance of the class), containing Random object variable be immutable?

The definition of immutability states that the state of an object (its data) cannot be altered after construction.
Here lays the question, in my opinion the state and the data the object contains are different things.
Maybe the state means the data that is provided via getters?
It does not mean data marked private and not visible to the outside world, that can indeed change and not alter the state of an object.
Tell me if this is correct:
final class Obj1 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
j = rnd.nextInt(1000);
return i;
}
}
An instance of Obj1 is an immutable object.
final class Obj2 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
return i;
}
public getJ() {
return j;
}
}
Is an instance of Obj2 a mutable or immutable object and why? What if we get the next Random in the body of getJ each time the getter is invoked?
And what about such a class? Mutable/immutable and why?
final class Obj3 {
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1() {
}
public getJ() {
return j;
}
}
What about this one? Mutable/immutable and why?
final class Obj4 {
private final Random rnd = new Random();
public Obj1() {
}
public getRnd() {
return rnd.nextInt(1000);
}
}
An important point about immutability is that the obeservable state of the object must not change.
A very good example is java.lang.String, which is often quoted as the canonical example for an immutable class. It has a single non-final field, which is hash. hash holds the hash code, but defaults to 0. The hash code is calculated lazily the first time hashCode() is called and cached in that field. This way the internal state of a String object can change, but the observable state never changes (because hashCode() always returns the same value, no matter if it is calculated or just returning the cached value).
This means that the first three samples you provided (Obj1, Obj2, Obj3) are immutable: They have no setter and nothing else can change the value returned by their methods after the construction (it would be a good idea to declare the fields final, but it's not a requirement for immutability). Note also you can also leave out the Random field entirely in those classes, as it's not used after construction anyway.
I'd say the last sample (Obj4) is definitely mutable, because you change the state (i.e. what the next getRnd() call returns) each time you read from it (i.e. each time you call getRnd()).
So, to answer the question in the title: yes, a class referencing a Random object can be immutable, if the state of the Random object is not observable in the state of the class itself.
Good question. But this is question of terminology, while immutability is more about how you can use objects. Benefits of immutable objects:
You can pass them by reference and be sure no one change its state;
You don't need to think about synchronization;
More secure to use as keys in hash maps.
I would not state object as immutable if it changes it's state after construction, even if it has to setters.
It is perfectly legitimate for an immutable object to hold, and even expose, references to objects of arbitrary type if the references are recognized as identifying, rather than holding, the objects in question. For example, consider an object reference as being analogous to a VIN (Vehicle Identification Number--an alphanumeric string that uniquely identifies a vehicle, at least those manufactured in, or imported to, the U.S.), and imagine a repair shop might keeps a list of the VINs of the cars it has serviced. The cars themselves would hardly qualify as immutable objects, but the list wouldn't hold cars--it would identify cars. One could not look at a VIN and know what color a car was at the time it was serviced, but when a car enters the shop one could use the list of VINs to determine whether the car had visited before.

Categories