strategy for defining immutable objects - java

I'm new to Java and is trying to learn strategy for defining immutable objects via Java tutorial Oracle. Due to my limited knowledge and probably how it was worded, I'm really struggling to understand the paragraph below, I was just wondering if anyone could kindly explain to me what it actually means. Thanks in advance for any help!
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.

Don't share references to the mutable objects
public class A {
private List<Integer> privateRef;
private int privateVal = 0;
public List<Integer> bad() {
return this.privateRef;
}
public int good() {
return privateVal;
}
}
The bad() method is bad because it exposes a reference to the private member, thus enabling a caller to do this:
A a = new A();
List<Integer> extractedRef = a.bad();
extractedRef.add(1);
Thus mutating a's private list (if you inspect a.privateList, you'll see that it contains 1). A no longer controls its internal state.
The good() method is good because even if a caller does:
A a = new A();
int number = a.good();
number++;
Even though number is 1, the value of a.privateVal remains 0.
Never store references to external, mutable objects passed to the constructor
Imagine we add this constructor to our class:
public class A {
...
public A(List<Integer> anotherList) {
this.privateRef = anotherList;
}
...
}
We're in a similar situation: mutations to the private list may happen externally:
List<Integer> list = new ArrayList<Integer>()
A a = new A(list);
list.add(1);
We have mutated a's internal state (if you inspect a.privateList, you'll see that it contains 1).
if necessary, create copies, and store references to the copies.
That is, if you wish A to be immutable, you should do this:
public A(List<Integer> anotherList) {
this.privateRef = new ArrayList<>(anotherList);
}
This way the new instance of A gets a copy of the list upon creation which becomes part of its internal state. From this point, mutations to the given list ("list" in the example) don't affect a's internal state: only a can mutate its private list.
Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
This is how you'd solve the first example, if A wants to expose its internal mutable list it should not do this:
public List<Integer> bad() {
return this.privateRef;
}
but
public List<Integer> better() {
return new ArrayList<>(this.privateRef);
}
At this point
A a = new A();
List<Integer> extractedRef = a.better();
extractedRef.add(1)
At this point, a.privateRef is still empty (so its state is protected from external mutation). But extractedRef will contain 1.
An additional point. Note that even though this class applies all the principles above:
public class A {
private List<Integer> privateRef = new ArrayList<>();
private int privateVal = 0;
public A(List) {
this.privateRef.addAll(this.privateRef);
}
public List<Integer> getList() {
return new ArrayList<>(this.privateRef);
}
public int getVal() {
return privateVal;
}
public void mutate() {
this.privateVal++;
this.privateRef.clear();
}
}
(It doesn't expose references to mutable objects, nor keep references to external mutable objects), it is not really immutable as there is a way to mutate its internal state (call mutate() on it).
You can of course remove mutate(), but a more correct alternative for immutability could be:
public class A {
private final List<Integer> privateRef = new ArrayList<>();
private final int privateVal = 0;
public A(List) {
this.privateRef.addAll(this.privateRef);
}
public List<Integer> getList() {
return new ArrayList<>(this.privateRef);
}
public int getVal() {
return privateVal;
}
}
(I haven't compiled the examples, but they should be almost ok).

Practically it says you don't want to expose your state to outside world, so outside world could modify your internal state as it wants. You don't want this because it's your business in that internal state, and someone could alter it. That's also why it recomands to create copies of you internal mutable object and pass them outside as copies. They will alter those copies, but will not have side effect on your internal state.

Example:
/**
* A simple mutable.
*/
class Mutable {
private int n;
public Mutable(int n) {
this.n = n;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
#Override
public String toString() {
return "Mutable{" + "n=" + n + '}';
}
}
// A thing that holds things.
class Thing<T> {
T m;
public Thing(T m) {
this.m = m;
}
public T getM() {
return m;
}
#Override
public String toString() {
return "Thing{" + "m=" + m + '}';
}
}
public void test() {
// Never store references to external, mutable objects passed to the constructor
Mutable m = new Mutable(10);
// t10 holds a reference to my mutable `m`, currently containing `10`
Thing<Mutable> t10 = new Thing<>(m);
// Now `m` holds `50`, even the one in `t10`.
m.setN(50);
// Make the new one holding `m` at value `50` now.
Thing<Mutable> t50 = new Thing<>(m);
// Both print the same because they both hold the same `m`
System.out.println("t10 = " + t10 + " t50 = " + t50);
// We can even mess with it after the fact - this is why you should return a copy.
t50.getM().setN(42);
// Both print the same because they both hold the same `m`
System.out.println("t10 = " + t10 + " t50 = " + t50);
}
This demmonstrates all three of the points made.
If you pass a mutable to a constructor and hold that mutable in the state, a change to that mutable will change the state of the object.
If you return a mutable it can also be modified outside your object, thus changing your state.
To avoid this:
If possible, use immutable in all cases.
If you must use a mutable in your constructor, take a copy of it if possible.
If you return the mutable anywhere, return a copy if possible.

While creating Immutable object, if there are mutable fields like Date object then following lines applies:
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.
The same can be achieved as follows :
Create a defensive copy of the Date object while creating immutable object.
Do not provide any setter methods for this Date Object.
If at all you need to provide getter method then, getter method should return a copy of the date field since Date itself is mutable. Here, clone() method helps to achieve this.
Now, Since there is no reference to the Date field in the class, any outside this class cannot modify the state of Immutable class.
Check Example for Immutable class

Related

Is it necessary to deep copy an array in java?

As far as I know and researched, arrays in Java are not objects but they're reference-types. My doubt is, when I want to return an array should I return a deep copy (like you would do with an object) with a clone() method for example, or can I return the variable countaining the array like it was a simple-type variable (ie. int or double) with a get method? For clarification porpuses, I will insert an example code to expose this situation:
public class List
{
// Instance Variables ----------
private int[] list1;
private int[] list2;
// Constructors ----------
public List()
{
list1 = new int[0]; list2 = new int[0];
}
public List(List x)
{
list1 = x.getList1();
list2 = x.getList2();
}
// Get methods
public int[] getList1()
{
return list1;
}
public int[] getList2()
{
return list2;
}
// Set methods
public void setList1(int size)
{
list1 = new int[size];
}
public void setList2(int size)
{
list2 = new int[size];
}
// Compare reference between an array and the instance variables
public boolean equals (int[] x)
{
if ( x == list1 || x == list2)
return true;
else
return false;
}
}
And now I have a TestClass the uses class List like this:
List listx = new List();
int[] listy = listx.getList2();
boolean test = listx.equals(listy);
System.out.printf("Result: " + test );
With this said, when I use the method equals to see if the two arrays share the same reference or adress, I get always the result true!! Am I breaking OOP basic principals with this? Will I loose control because listy is pointing to listx instance variable?
Well, I'm really confused with this and I don't know if this is right(being array a non-instantiable class) or If I should send some kind of deepcopy insted of shallow using a Clone method in other to ensure that all basic OOP principals are fulfilled, and with this principals I mean that the class method should be acessed only by the API and that the internal state(instance variables) can only be acessed by the class itself.
You are not breaking OOP principals. However, you are breaking principals of functional programming. Functional programming views leaking of access as losing of control.
Whether or not you want to practice functional programming is up to you, Java doesn't take a stance in that matter.
You may want to consider if it's important not to leak access for this particular class. If you find it important not to leak access then make this class immutable.
You can also guard the instance variables. In this scenario any possible changes to the variables must be handled by the instance class. However, the instance could be modified from separate contexts and result in loss of control. For this reason functional programming only allows immutable classes.
If you want the invoker of the method to be able to modify the original array, you don't need to do a copy. Otherwise, you do.
Check your implementation of equals(). It should be reflexive, symmetric, and transitive, which is not the case on yours.
It depends on your use-case if you want to deep copy or not. If your elements are immutable you normally not need to do a deep copy. If they can change, it depends if you want to see the changes in your receiver of the copy or not. Typically when you want a snapshot of the given data you will have to deep copy it. However keep in mind that Arrays are most of the time not a good argument or return type for APIs anyway.

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.

Assigning value of an object to another - they mustn't point same adresses at memory

I have a problem with getting a new value of an object. I have a code like that:
...
TimeSchedule[] offspringScheduleOne = new TimeSchedule[AVAILABLE_CLASSROOMS];
...
offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i];
...
After that assignment offspringScheduleOne[i] and genes.get(geneOneIndex).getSchedule()[i] points the same memory address. I want that: offspringScheduleOne[i] should get the value of the genes.get(geneOneIndex).getSchedule()[i], they musn't be same, they just should have same values.
TimeSchedule class:
public class TimeSchedule extends AlgorithmParameters {
public int[][] timetable = new int[DAYS][HOURS];//DAYS and HOURS are static final variables that comes from AlgorithmParameters
public int[][] getTimetable() {
return timetable;
}
public void setTimetable(int[][] timetable) {
this.timetable = timetable;
}
}
How can I do that?
It actually is copying the value - but you need to understand what that value is.
The value of offspringScheduleOne[0] isn't a TimeSchedule object. It's a reference to a TimeSchedule object. No expression in Java has a value which is an object. It's really important that you understand this.
Now, if you want a copy of the object, you'll have to make that happen yourself. For example, you could include a clone() method in TimeSchedule, and write:
offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i].clone();
In other words, create a clone of the existing object, and then set offspringScheduleOne[i] to be a reference to that newly created object. Of course, if any of the fields within TimeSchedule is a reference type field, you'll need to consider whether or not you need to clone that object as well...
... or you could add a constructor and call that, or another method, etc. But you need to be absolutely clear that the assignment operator is copying the value, but that value is a reference.
EDIT: Okay, now that you've posted TimeSchedule, a few suggestions:
Stop using public fields. What's the point of having properties if the field is public?
Rather than having properties returning the whole array, change them to access an individual hour, e.g.
public int getTimetable(int day, int hour) {
// TBD: Argument validation
return timetable[day][hour];
}
// Similar for `setTimetable`
Create a clone method like this:
public TimeSchedule clone() {
TimeSchedule copy = new TimeSchedule();
for (int i = 0; i < timetable.length; i++) {
copy.timetable[i] = timetable[i].clone();
}
return copy;
}
(That's slightly wasteful in that it will create the subarrays and then discard them, but let's get something which works first...)
}
public Test clone() {
int[][] timetableCopy = new int[timetable.length][];
for (int i = 0; i < timetable.length; i++) {
timetableCopy[i] = timetable[i].clone();
}
return null;
}
You should create a new TimeSchedule object. Assuming you have a copy constructor you can use this:
TimeSchedule original = genes.get(geneOneIndex).getSchedule()[i];
TimeSchedule copy = new TimeSchedule(original);
offspringScheduleOne[i] = copy;
The constructor should copy the values from original. If you don't have such a constructor you can call get and set methods to copy the values across manually.
TimeSchedule original = genes.get(geneOneIndex).getSchedule()[i];
TimeSchedule copy = new TimeSchedule();
copy.setFoo(original.getFoo());
copy.setBar(original.getBar());
// etc...
offspringScheduleOne[i] = copy;
There's also a clone method that was designed for creating copies of objects, but it's awkward to use and it's probably best to avoid it.
You could let TimeSchedule override the clone method and write
offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i].clone();

Java Object Oriented Design: Returning multiple objects in java

The below code in Java throws Null pointer exception.
public class New{
int i;
New(int i)
{
this.i = i;
}
public void func(New temp)
{
temp.i = 10;
temp = new New(20);
}
public static void main(String[] args)
{
New n = null;
n.func(n);
System.out.println("value "+ n.i);
}
}
The reason being, java passes objects references by value. If I wanted to return one object, then I can return it from the function.
But, If I have multiple objects, the only way I could return the object references is, by keeping them into another object, like having some container which has references to all the objects.
Is there a better way to do it?
In C++, I normally just pass the address of pointer to handle this scenario. If I wanted to just return two objects of a single type, creating a container and passing it is a over kill.
What is the problem with returning multiple objects from a function? Why cannot the semantics of the function in all these languages be changed?
Most often you create an object to hold the combination of objects you want to return.
For a more general-purpose solution, you can either return a collection, and array or some sort of tuple, such as Pair, Triple, etc (the latter you will need to create).
Note, you don't generally pass a mutable object as a parameter, but return an immutable one:
public Pair<Integer,Integer> getLowHighTemp() {
int low,hgh;
// do stuff...
return new Pair(low,hgh);
}
This is more of 2 questions than one.
Firstly the problem with your code is that you are not declaring n before you use it. That is throwing the exception.
Secondly if you would like to return 2 objects, you need to have a container object that will hold 2 objects.
You can return some kind of Collection. Returning a Map or List is pretty common.

Copy an object in Java

I have an object that I need to copy in Java. I need to create a copy and run some tests on it without changing the original object itself.
I assumed that I needed to use the clone() method, but this is protected. Having done some research on the net, I can see that this can be overriden with a public method in my class. But I cannot find an explanation on how to do this. How could this be done?
Also, is this the best way of achieving what I need?
Another option by using Copy Constructor (from Java Practices):
public final class Galaxy {
public Galaxy (double aMass, String aName) {
fMass = aMass;
fName = aName;
}
/**
* Copy constructor.
*/
public Galaxy(Galaxy aGalaxy) {
this(aGalaxy.getMass(), aGalaxy.getName());
//no defensive copies are created here, since
//there are no mutable object fields (String is immutable)
}
/**
* Alternative style for a copy constructor, using a static newInstance
* method.
*/
public static Galaxy newInstance(Galaxy aGalaxy) {
return new Galaxy(aGalaxy.getMass(), aGalaxy.getName());
}
public double getMass() {
return fMass;
}
/**
* This is the only method which changes the state of a Galaxy
* object. If this method were removed, then a copy constructor
* would not be provided either, since immutable objects do not
* need a copy constructor.
*/
public void setMass( double aMass ){
fMass = aMass;
}
public String getName() {
return fName;
}
// PRIVATE /////
private double fMass;
private final String fName;
/**
* Test harness.
*/
public static void main (String... aArguments){
Galaxy m101 = new Galaxy(15.0, "M101");
Galaxy m101CopyOne = new Galaxy(m101);
m101CopyOne.setMass(25.0);
System.out.println("M101 mass: " + m101.getMass());
System.out.println("M101Copy mass: " + m101CopyOne.getMass());
Galaxy m101CopyTwo = Galaxy.newInstance(m101);
m101CopyTwo.setMass(35.0);
System.out.println("M101 mass: " + m101.getMass());
System.out.println("M101CopyTwo mass: " + m101CopyTwo.getMass());
}
}
There are two popular approaches. One is to provide a clone method as you mentioned, like so.
public class C implements Cloneable {
#Override public C clone() {
try {
final C result = (C) super.clone();
// copy fields that need to be copied here!
return result;
} catch (final CloneNotSupportedException ex) {
throw new AssertionError();
}
}
Pay attention to the "copy fields ... here!" part. The initial result is only a shallow copy, meaning that if there's a reference to an object, both the original and result will share the same object. For example, if C contains private int[] data you'd probably want to copy that.
...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...
Note that you don't need to copy primitive fields, as their content is already copied, or immutable objects, as they can't change anyways.
The second approach is to provide a copy constructor.
public class C {
public C(final C c) {
// initialize this with c
}
}
Or a copy factory.
public class C {
public static C newInstance(final C c) {
return new C(c);
}
private C(final C c) {
// initialize this with c
}
}
Both approaches have their respective properties. clone is nice because its a method, so you don't have to know the exact type. In the end, you should always end up with a "perfect" copy. The copy constructor is nice because the caller has a chance to decide, as can be seen by the Java Collections.
final List c = ...
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?
final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties
I recommend choosing either approach, whichever suits you better.
I'd use the other approaches, like reflective copying or immediate serializing/deserializing, in unit tests only. To me, they feel less appropriate for production code, mainly because of performance concerns.
Some options:
You can implement Cloneable for your object and put clone() method as public. See full explanation here: http://www.cafeaulait.org/course/week4/46.html
However, this produces a shallow copy and might be not something you want.
You can serialize and deserialize your object. You will need to implement Serializable interface for the object and all its fields.
You can use XStream to perform serialization via XML - you won't have to implement anything here.
For test code Serialization is maybe the safest answer, especially if the object is already Serializable try Apache Commons SerializationUtils for an implementation.
You can use org.apache.commons.lang3.SerializationUtils class for object cloning,
- Class should implement Serializable interface.
ClassName copyobject = SerializationUtils.clone(classobjectTocopy)
SerializationUtils.clone is also supported on Google App Engine instance
Joshua Bloch has some interesting things to say about cloneable. Depending on the size/construction of the object, I'd add a copy constructor to the object, or serialise/deserialise using one of the solutions mentioned above.
There are multiple ways to copy object in java(shallow or deep).
This Answer will help you.

Categories