Morgan Stanley Interview Question
Java DevelopersCountry: India
Interview Type: Phone Interview
+1, Good answer.
Why do you say using immutable objects reduces the garbage collection overhead, though? Since you have to discard an immutable object and create a new one every time you want the value to change, I would generally expect the effect on garbage collection to be somewhat the opposite.
With immutable objects, we can avoid circular references and make GC's life easier.
I found the answer from Brian Goetz's article.
In most cases, when a holder object is updated to reference a different object, the new referent is a young object. If we update a MutableHolder by calling setValue(), we have created a situation where an older object references a younger one. On the other hand, by creating a new ImmutableHolder object instead, a younger object is referencing an older one. The latter situation, where most objects point to older objects, is much more gentle on a generational garbage collector. If a MutableHolder that lives in the old generation is mutated, all the objects on the card that contain the MutableHolder must be scanned for old-to-young references at the next minor collection. The use of mutable references for long-lived container objects increases the work done to track old-to-young references at collection time.
Well Immutable Objects are those whose value cannot be changed.. it is used basically to increase the security of the the system.
@Saurav and Rage:
Nyc points and implementation. But can you elaborate about its reusability.
@techieDeep
suppose your application needs several such objects(hundreds of thousands) , so for increasing the throughput of your application , instead of creating an object everytime , you can look into already existing objects table and assign an 'equal' object to it.
Precisely same is done in case of String class in java. Infact, it was the main reason to make String immutable.
Immutable objects are simply objects whose state (the object's data) cannot change after construction. Examples of immutable objects from the JDK include String and Integer.
And here is the answer to your question other question:
public class Mydate {
private final Date date;
public Mydate(Date date) {
this.date = new Date(date.getTime());
}
public getDate() {
return date;
}
}
Since the date object passed in the constructor was created elsewhere you cannot sheild it from being changed unless you create a copy of it and use that in this class
@Rage:
Do we have to take care not to make date instance/reference available outside the object through getDate().
I mean what if the returned date object is modified outside....I know we cannot re-initialize as it is declared final, but date can be manipulated?
Yes , but instead creating a new Class for storing Date, we could use do that in our constructer itself.
// both name and date are marked final
immutable(String name,Date date)
{
this.name = name;
// create own copy, initialize it for the date object given , could have used copy constructer if any.
this.date = new Date(date.getTime());
}
@sai: references of final object are always mutable. To make date immutable via getDate change the return type to final Date instead of Date
@Rage: you can't set the return type of a method to be final.
public final Date foo() { ... } does something very different than what you seem to think. It does not return an immutable object; rather, it seals the method from extension by subclasses. The "final" here is not part of the return type (the return type is still Date). I think that maybe you're equating "final" with "const" in C++, and they are not equivalent.
Your initial answer is not correct because you class is entirely mutable: I can change its state by calling yourObject.getDate().set(myNewTime). Simply creating a defensive copy on construction does not make your object immutable, but only makes there be no reference to the internals of the class on object instantiation. If you later leak references to the internals of your class (like your getDate() method does), the class is still mutable. What you need is a defensive copy both on construction and on returning internals. Copy-on-construction ensures that there are no external references to the internals of the class at the time the object is initialized. Copy-on-get ensures that no such references come to exist at a later time.
Assuming Date has a copy constructor, the full solution would be as follows:
public class ImmutableDate
{
//the final here isn't strictly necessary, because this field isn't
//externally visible anyway
private final Date date;
public ImmutableDate(Date date)
{
this.date = new Date(date);
}
public Date getDate()
{
return new Date(this.date);
}
}
Agree with @eugene,yarovoi. We have to make defensive copy in both contructors and getters.
How about this implementation:
public final class ImutableDate extends Date {
private static final long serialVersionUID = 0xFEEDF00DL;
public ImutableDate(long time) {
super(time);
}
@Override
public void setTime(long time) {
throw new IllegalStateException("Cannot modify Imutable date object");
}
}
@HG: that works too, though I tend not to prefer that kind of approach, largely because illegal uses cannot be detected until runtime (the compiler can't catch them). The technique is very useful if you must be able to accept an ImmutableDate anywhere that you can accept a Date, however.
@HG: Collections.unmodifiableMap(...) in Java uses this approach to immutability, actually.
immutable objects can note be changed using methods. we can only use these objects. we can not change them because there is no set methods. it leads to simple and reliable code.
public class Data{
private Date date;
public Data(date){ //date is set to the object and cannot change anymore
this.date=date;
}
public getDate(){ //this helps to take the value inside the object
return date;
}
//please note that there is no way to change the value in the object..thats why it is called a //immutable object
}
If Date is a mutable reference type (as seems to be the case here), your getDate() method leaks the reference and allows instances of the Data class to be modified.
yes... the Date Object should be a constant..otherwise it can be changed..
so the corrected definition should be like this..
public class Data{
private Final Date date;
....
public void getDate(){
....
Marking it as final doesn't make it a constant. It just means you can't assign to the member, a goal which was already being accomplished by the use of the private keyword and the lack of a setter. You can't reassign what object the "date" field points to, but the object itself can still be changed. When getDate() returns the instance of the Date class, that instance can still be modified.
For ways of solving this problem, see my and HG's comments to Rage's answer.
An object is considered immutable if its state cannot change after it is constructed.
Advantages :
1. Simple and Reliable Code.
2. Useful in concurrent Applications since they cannot change state, they cannot be corrupted by thread interference or present in inconsistent state.
3. Decreased overhead in Garbage Collection.
4. Reduction in code needed to protect objects in concurrent applications.
JDK Examples : String, Integer
- vinayknl.61 February 20, 2013