How String achieves immutability? - java

In one of the interview I was asked 'How String is made immutable?'
As i wasnot sure about the answer, i didnot reply. I asked the interviewer later regarding the same. Answer was String class is final that's how immutability is achieved.
Is that the correct answer? if yes, even StringBuffer is also marked as final class. Then why not StringBuffer is immutable?

It is a combination of:
Fields are private - so you cannot change them directly.
No set methods provided - so they cannot be changed indirectly either.
String is final - so you cannot add mutability (i.e. setters etc.) to it.

No that's not the correct answer. String achieves immutability because it doesn't provide you any method to change its internal contents. Thus you can instantiate a String object, assign a reference to it but cannot change its contents once initialized.

String is immutable object.
Make a class immutable by following these guidelines :
ensure the class cannot be overridden
make the class final, or use static factories and keep constructors private
make fields private and final
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
if the class has any mutable object fields, then they must be defensively copied when passed between the class and its caller
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)

The final keyword is not the same as immutability. String is immutable as it does not define any methods that allow a user to change its content and it is final, removing the possibility to change things in a subclass.
Making something like a List instance variable final will still allow you to change its contents, making it mutable.

Being final means it can't be derived from. That doesn't confer immutability
Immutability is achieved by encapsulation and not providing any means to amend the internally held character array. I.e. no methods exist to modify the internal fields.

A pool of strings, initially empty, is maintained privately by the class String.
You should look at the JavaDoc of String:
public native String intern();
See:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern%28%29
http://en.wikipedia.org/wiki/String_interning

The usual way to make a class immutable is to ensure that:
all the fields are private;
there is no way to modify the fields after construction;
it is final (so that extensions cannot break immutability).
String is a bit special, at least in the Sun/Oracle implementation in that it does not actually follow this procedure. The implementation has a mutable field in which it caches the hash code of the object. So while there is a method that changes the internal state of the object (hashCode), this state change does not change the behaviour of the object in any way. Any subsequent calls to hashCode will run faster, but the result won't be any different.

Related

How does one know if a certain method will change the state of a java object?

Some methods are mutator methods, usually they return nothing, the so-called setters. Others, like the .plusDays() method of the LocalDate class, return a full, instantiated object of type Localdate, so if you want to change the object, you need to point your existing object variable to the newly created one.
Is there a way to know beforehand if a method will be a mutator, or work like the before-mentioned apart from looking at its return value?
No, there is no way to know (short of looking at the documentation or implementation) whether a method will change some sort of state.
Methods that return void are generally going to change some sort of state (otherwise what are they doing?), but there's still no guarantee what will change (options include the object, one of its fields, the method's parameters, global state, or even the JVM runtime itself).
There's no general-purpose way to tell whether methods that return something will also have other side-effects or not.
If a type is immutable you can be confident that none of its methods will mutate its own state, but then the question has simply shifted to "how do you tell whether a type is immutable or not?" This is easier to answer, but still tricky. Static analysis tools like ErrorProne's #Immutable check are helpful but still fallible.
Well, pure setters which follow the pattern void setProperty(PropertyType property) are likely to modify the internal state (ok, one could implement it in a different way, e.g. modify the state of the passed parameter, but that would be strange).
Methods found in Builders for instance (like Builder withProperty(PropertyType property)) are free to choose whether they update the state of the actual instance or create and return new instance holding the updated property.
In the end one cannot foresee whether one or the other implementation strategy has been chosen just by looking at the method, so one has to read the docs (and sometimes the code).

Does Java have a concept of reference ownership or noncopyable classes?

I would like to have some guarantee that instances of some particular class Content is only accessed by its "owner", and if another object wants the same Content it needs to take a deep copy. Coming from C++ I would achieve that using a unique_ptr, is there anything similar in Java?
Currently I am resolving this by just keeping the Content private everywhere I keep one and paying attention to creating a new Content (the constructor implements the deep copy mechanism) on a getContent. But I have no means of enforcing possible other users of the Content class to follow the same pattern, it's easy to forget. It would be nicer if it could take care of itself somehow, like not being copyable.
I realize that it goes somewhat against the spirit of the language, but in some cases I think it's justified. For example, if Content represents some stream of data that is modified even by reading it. I thought, if not in the core language, maybe there is some #interface for compile-time checking or a way of creating one?
Edit: The idea is that the owner can modify the object freely, before or after taking copies, and if someone takes a deep copy, they can modify theirs (not affecting the original), so making the Content immutable is a bit too harsh (unless I'm misunderstanding what that implies).
There are a couple of common strategies here:
Privacy with defensive copying
In this strategy, you'd have the owner have a private reference to the content, and if it's appropriate for it to give out copies of that content, to do so via a defensive copy:
class Owner {
private Content content;
// ...unnecessary detail omitted...
public Content getContent() {
return new Content(this.content);
}
}
The Cloneable interface can sometimes be useful here.
Immutable objects
The other common strategy is to use immutable objects (e.g., ensure that Content, once instantiated, cannot be modified). Then you don't care who has a reference to the content, since they cannot change it.
No there isn't.
Once you have established a reference to an object, there's absolutely nothing you can do to stop someone form assigning another reference to that object via that established reference.
Java programmers get round this by making objects immutable (see java.lang.String). Then you ought not give two hoots about who else is referring to a particular instance.
You can declare the class Content as Immutable by doing this:
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.
If the instance fields include references to mutable objects, don't allow those objects to be changed
Here is a java official doc: https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
Java does not have something like that. There are some language elements that can help with such requirements:
Enums that have only one constant; to be used as "built-in" singletons
Methods in Collections to create immutable copies of collections
And of course, you can make all fields in your class final; so they get initialized only during construction time; to prevent later changes
But as Java is also missing a const concept, you can partially work around such things. Like in:
class Foo {
private final List<Bar> bars = new ArrayList<>();
doesn't mean that instances of Foo will be immutable - as you still can add/remove elements to that list owned by Foo.
Similar; given
List<Foo> root = ...
List<Foo> immutableCopy = Collections.unmodifiableList(root);
one can still change that immutableCopy ... by messing up root.

Class design, case for static methods

I had a discussion about usage of static method, briefly the argument is should a class definition have a method as static or instance method in the following scenario. There is a class that defines an entity i.e, what its properties are and what operations are allowed on it.
class dummy{
String name;
String content;
String someRandomOpeation(){
....
}
static String createKey( String inputName, String inputContent ){
return inputName+inputContent;
}
}
The class definition also has a static method that takes in some arguments (say content and date, which defines an instance logically) and use it to construct a key (a string) and return the same. Now if an instance of the message is created it would have the content and date as fields. Is the argument that I can get a key given a name and content and not have to create an instance valid to have the static method. Or does the fact that a pair of name and content logically define an instance say that an instance to be created and get a key from that?
Having a method as static just because you do not wish to instantiate is NOT a valid argument. According to design we use static methods in helper/util classes which may or may not have any properties of its own. These classes basically help in performing some common action which many different classes can use. Also the functions are so modular that they only use the arguments passed to the function to derive the output.
The class mentioned by you will not work because you cannot make a static reference to a non static field constant in JAVA.
Moreover, the disadvantage of using static methods strictly associated with its class fields is that you can not override them.
Is the argument that I can get a key given a name and content and not
have to create an instance valid to have the static method.
No. In this case you almost do not need a class at all. You can always pass data members to class methods, but that does not mean that we do not need classes.
There is an additional argument - encapsulation. It is much clearer and niced to have an instance method getKey() with no arguments and hide the implementation details.
Or does the fact that a pair of name and content logically define an
instance say that an instance to be created and get a key from that?
Also no. The fact itself does not mean that you should create an instance.
The first question here is wether we need a class or not. Do we really have some meaningfull objects, instances of something (dummy)? For example, if I have a library, it obviously make sense to have a class Book, as I have lots of books around. Do you have such a situation? Is this key logically associated with an instance of whatever (dummy here), in a way that Author and ISBN are logically associated with a Book? Does instances of this concept (dummy) has some relationships with some other concepts? Like a Book can be rented.
If most of these answers is yes - than this method should be instance method with no arguments.
Or...
Do you maybe only need kind of a "service" that calculates a key from 2 strings? It this all you need? Are there some other similar "services" that you need, independent on instances. If these answers are mostly "yes", that you do not even need a class. Or you can have a class "Services", with no attributes and with this static method and arguments (and maybe additional methods).
There is also a mixed situation. You still need instances for some other purpose, but you also need a createKey method that is totally independent on any instance, and only provide some global service that is somehow related with the class logic. Then a static method can make sense.
I think your way of thinking is kind of function-oriented instead of object oriented. I think you need a "click" in your mind, which would help you understand the right purpose and the meaning of objects and classes.

Should I set references to mutable objects final when possible?

I understand that it is a good practice to use final for object fields that are 1) set only once in the constructor 2) reference to an immutable object.
What about fields that are set only once in the constructor but reference to a mutable object?
Currently, I prefer using final only for immutable object references, because I can quickly see which fields represent the mutable state of the object (those that are not final).
Update: I know how final works technically, specifically that setting a reference to a mutable object as final won't make the object immutable. This question is about when exactly use final if I want to maximize clarity and understandability of the code.
This might not be a popular opinion, but I use final wherever possible - if you're using it to declare intent, then that can be done with comments. If your reaction to that is that "comments are bad", then you should reconsider the use of the final keyword also - as it's basically a comment, right?
However, the final keyword does provide a (almost) guarantee to anyone reading the code that that variable isn't reset anywhere (ignoring reflection of course...) - which is a useful thing to know at times.
You might also be interested in Jon's answer to this question
EDIT: Sorry, I should clarify that "wherever possible" applies to fields - not classes, methods etc. because that would be weird.
Even if you declare the variable final the referenced object will still be mutable. So if this is what you are trying to avoid then it would not work (I mean make the referenced object immutable)

Possible ways of making an Object immutable

I am looking for some efficient way for building a immutable class, just like Java's String class.
All the fields must be
private and preferably final
Ensure the class cannot be
overridden - make the class final,
or use static factories and keep
constructors private
Fields must be populated from the
Constructor/Factory
Don't provide any setters for the
fields
Watch out for collections. Use
Collections.unmodifiable*. Also, collections should contain only immutable Objects
All the getters must provide
immutable objects or use defensive copying
Don't provide any methods that
change the internal state of the
Object.
Tom Hawtin pointed out that final can be optional. String class has a cache hash var that is only assigned when the hash function is called.
If you populate all fields using the constructor and make the fields final - you are partway there.
If the fields use custom types - you may need to make them immutable as well.
Any fields that are collections should use the unmodifiable collections - to be on the safe side.
You need to worry about the object graph!
Any methods on the object need to take care with non-final fields. E.g. String.add creates a new String. If you need to mutate one field - do so via a copy constructor.
Finally make the object final.
An object is immutable if none of its fields can be modified, so those fields must be final. If you don't want your object to be subclassed, you can make the class itself final as well, just like String is.
To easily construct an immutable object with a lot of information, you should look at the Factory Pattern
For more information, see Wikipedia

Categories

Resources