I actually thought that I had a good idea of how passing values in Java actually work, since that was part of the SCJP cert which I have passed. That was until today, when I at work discovered a method like this:
public void toCommand(Stringbuffer buf) {
buf.append("blablabla");
}
Then the caller of that method used the function like this:
StringBuffer buf = new StringBuffer();
toCommand(buf);
String str = buf.toString();
Now I thought that that code would give str the value "", but it actually give it the value from the mehod. How is this possible? I thought things didnt work like that in Java?
Either way... it should be considered a bad practice to write code like this in Java, right? Because I can imagine it can bring some confusion with it.
I actually spent some time searching on this, but my interpretation of what these sources are saying, is that it shouldnt work. What am I missing?
http://www.yoda.arachsys.com/java/passing.html
http://javadude.com/articles/passbyvalue.htm
Sebastian
Java is pass-by-value. The value of an object reference is an object reference, not the object itself. And so the toCommand method receives a copy of the value, which is a reference to the object — the same object that the caller is referencing.
This is exactly the same as when you're referencing an object from two variables:
StringBuffer buf1;
StringBuffer buf2;
buf1 = new StringBuffer();
buf2 = buf1; // Still ONE object; there are two references to it
buf1.append("Hi there");
System.out.println(buf2.toString()); // "Hi there"
Gratuitous ASCII art:
+--------------------+
buf1--------->| |
| === The Object === |
| |
buf2--------->| Data: |
| * foo = "bar" |
| * x = 27 |
| |
+--------------------+
Another way to think of it is that the JVM has a master list of all objects, indexed by an ID. We create an object (buf1 = new StringBuffer();) and the JVM assigns the object the ID 42 and stores that ID in buf1 for us. Whenever we use buf1, the JVM gets the value 42 from it and looks up the object in its master list, and uses the object. When we do buf2 = buf1;, the variable buf2 gets a copy of the value 42, and so when we use buf2, the JVM sees object reference #42 and uses that same object. This is not a literal explanation (though from a stratospheric viewpoint, and if you read "JVM" as "JVM and memory manager and OS", it's not a million miles off), but helpful for thinking about what object references actually are.
With that background, you can see how toCommand gets a reference (42 or whatever), not the actual StringBuffer object data. And so operations on it look it up in the master list and alter its state (since it holds state information and allows us to change it). The caller sees the changes to the object's state because the object holds the state, the reference just points to the object.
Either way... it should be considered a bad practice to write code like this in Java, right?
Not at all, it's normal practice. It would be very hard to use Java (or most other OOP languages) without doing this. Objects are big compared to primitives like int and long, and so they're expensive to move around; object references are the size of primitives, so they're easily passed around. Also, having copies of things makes it difficult for various parts of a system to interact. Having references to shared objects makes it quite easy.
StringBuffer is mutable. The toCommand() method gets a reference to that objects which is passed by value (the reference), the reference allows the method to change the mutable StringBuffer.
If you are thinking about why we cannot do this with String it is because String is immutable in which case it will result in the creation of another String object and not having the changes reflected in the object of which the reference is passed.
And I don't see why it should be bad practice.
This is because the in the method, when you pass an object, a copy of a reference to the object is passed by value. Consider the example below:
public class Test {
public static void modifyBuff(StringBuffer b) {
b.append("foo");
}
public static void tryToNullifyBuff(StringBuffer b) {
b = null; // this will not affect the original reference since
// the once passed (by value) is a copy
}
public static void main(String[] args) {
StringBuffer buff = new StringBuffer(); // buff is a reference
// to StringBuffer object
modifyBuff(buff);
System.out.println(buff); // will print "foo"
tryToNullifyBuff(buff); // this has no effect on the original reference 'buff'
System.out.println(buff); // will still print "foo" because a copy of
// reference buff is passed to tryToNullifyBuff()
// which is made to reference null
// inside the method leaving the 'buff' reference intact
}
}
This can be done with other mutable objects like Collection classes for example. And this is
not at all a bad practice, in fact certain designs actively use this pattern.
str has the value "blablabla" because a reference to the StringBuilder instance is passed to toCommand().
There is only one StringBuffer instance created here - and you pass a reference to it to the toCommand() method. Therefore any methods invoked on the StringBuffer in the toCommand() method are invoked on the same instance of the StringBuffer in the calling method.
It is not always bad practise. Consider the task to assemble an email, then you could do something like:
StringBuilder emailBuilder = new StringBuilder();
createHeader(emailBuilder);
createBody(emailBuilder);
createFooter(emailBuilder);
sendEmail(emailBuilder.toString());
It surely could be used to create confusion and for public API one should add a note or two to the javadoc, if the value at the passed reference is changed.
Another prominent example from the Java API:
Collections.sort(list);
And as other already explained and just to complete the answer: The value of the reference of the StringBuffer (<-- start using StringBuilder instead!) is passed to toCommand so outside and inside the toCommand method you access the same StringBuffer instance.
Since you get a reference to the instance you can call all the methods on it, but you can't assign it to anything else.
public void toCommand(Stringbuffer buf) {
buf.append("blablabla"); // okay
buf = new Stringbuffer(); // no "effect" outside this method
}
When you pass an object to a method, unlike in C++, only the reference to the object gets copied. So when a mutable object is passed to the method, you can change it and the change gets reflected in the calling method.
In case you're too much into C/C++ programming, you should know that in java, pass by reference(in C++ lingo) is the default(and the only) way of passing arguments to methods.
Just in response to some of the comments about the SCJP (sorry don't have permissions to leave comments - apologies if leaving an answer is not the right way to do this).
In defence of the SCJP exam, passing object references as method parameters AND the differences between immutable String objects and StringBuffer / StringBuilder objects are part of the exam - see sections 3.1 and 7.3 here:
http://www.javadeveloper.co.in/scjp/scjp-exam-objectives.html
Both topics are covered quite extensively in the Kathy Sierra / Bert Bates study guide to the exam (which is the de facto official study guide to the exam).
Related
I'm reading the "Java Concurrency in Practice" book and there is a part that I don't quite understand. I know is an old book, and probably is the reason why there is no mention of my doubt.
In the "Sharing object" chapter there is a the section called "Publication and escape":
Publishing an object means making it available to code outside of its
current scope, such as by storing a reference to it where other code
can find it, returning it from a nonprivate method, or passing it to a
method in another class ...
An object that is published when it
should not have been is said to have escaped.
And there is an example:
class UnsafeStates
{
private String[] states = new String []
{"AK", "AL" ....};
public String [] getStates(){return states;}
}
Publishing states in this way is problematic because any caller can
modify its contents. In this case, the states array has escaped its
intend scope, because what was supposed to be private state has been
effectively made public.
And is specified to don't do never in this way.
I suddendly thought about the encapsulation concept where, basically, say to do exactly this.
I misunderstood the concepts or what?
The problem is this method:
public String [] getStates(){return states;}
Return your reference to states array.
Even though you declare states as private but if you get it via getStates() method, you still can modify the states variable:
UnsafeStates us = new UnsafeStates();
String[] copyStates = us.getStates();
copyStates[0] = "You don't know"; // Here the change to `copyStates` also affect the `states` variable since they're both reference to the same array.
Normally, for objects and array properties, you often return a deep copy of that properties to prevent modify internal properties.
Ex: For array:
String[] copied = new String[states.length];
System.arraycopy(states, 0, copied, 0, states.length);
return copied;
For List:
return Collections.unmodifiableList(internalList);
For Object:
return internalObject.clone(); // Require deep clone
I'm considering creating the following method:
public static MyBigCollection doSomeStuff(MyBigCollection m) { ... return m; }
and then in another method (perhaps in another class), using it like so:
MyBigCollection mbc = new MyBigCollection();
mbc = stuffClass.doSomeStuff(mbc);
Am I going about this the right way -- is this an efficient way to "do some stuff" to an object? I'd like to break off the stuff like so for extensibility. I've been doing c# for so long I'm just not sure with java. In c# the method could return void and I can simply call doSomeStuff(mbc) -- which would effectively pass my object by reference and do some stuff to it. I've been reading that java works differently so I wanted to check with the experts here.
I'd refactor to:
stuffClass.doSomeStuff(mbc);
(i.e., a method that modifies mbc and returns void)
Keep in mind that all Java Objects are stored in heap memory, and passed around with reference pointers.
The way you're doing it is fine, but you don't actually need to return the object at the end of the method. As such, the following would be simpler...
MyBigCollection mbc = new MyBigCollection();
stuffClass.doSomeStuff(mbc);
Objects in Java are passed by reference, so any modification on the mbc Object in the doSomeStuff() method would still be retained in the mbc variable after the end of the method call.
The only reason why you might consider returning the mbc Object is if you want the ability to join multiple methods together, such as this...
MyBigCollection mbc = new MyBigCollection();
mbc.doStuff1().doStuff2().doStuff3();
In this case, because mbc is returned by each of the doStuff() methods, the next method can be called straight back on to the same Object. Without returning the reference, you'd have to do something like this instead...
MyBigCollection mbc = new MyBigCollection();
mbc.doStuff1();
mbc.doStuff2();
mbc.doStuff3();
Which is the same thing, but not quite as compact. How you go about it really depends on how you intend to use the methods and the Object itself.
There's only one way to pass Java objects around. Java passes everything by value. Objects aren't passed; they live on the heap. You pass references around, not objects.
Same as C#, as far as I know.
This kind of micro-optimization is usually meaningless.
I think your question is around how Java passes references to objects. Java passes by value, which can be confusing when first said. For objects, this means that the value of the reference to the object is passed to the method. Interacting with the object referred to by the value will alter the object 'passed in', so you don't need to return it.
Strings are treated differently as they are immutable. Primitives are also pass by value, but as the value passed is not a reference, you will not alter the original variable.
The easiest way to test this is to write some code and observe (you might also consider the Java tutorials)
Since arguments sent to a method in Java point to the original data structures in the caller method, did its designers intend for them to used for returning multiple values, as is the norm in other languages like C ?
Or is this a hazardous misuse of Java's general property that variables are pointers ?
A long time ago I had a conversation with Ken Arnold (one time member of the Java team), this would have been at the first Java One conference probably, so 1996. He said that they were thinking of adding multiple return values so you could write something like:
x, y = foo();
The recommended way of doing it back then, and now, is to make a class that has multiple data members and return that instead.
Based on that, and other comments made by people who worked on Java, I would say the intent is/was that you return an instance of a class rather than modify the arguments that were passed in.
This is common practice (as is the desire by C programmers to modify the arguments... eventually they see the Java way of doing it usually. Just think of it as returning a struct. :-)
(Edit based on the following comment)
I am reading a file and generating two
arrays, of type String and int from
it, picking one element for both from
each line. I want to return both of
them to any function which calls it
which a file to split this way.
I think, if I am understanding you correctly, tht I would probably do soemthing like this:
// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
// would use appropriate names
private final int intVal;
private final String stringVal;
public Line(final int iVal, final String sVal)
{
intVal = iVal;
stringVal = sVal;
}
public int getIntVal()
{
return (intVal);
}
public String getStringVal()
{
return (stringVal);
}
// equals/hashCode/etc... as appropriate
}
and then have your method like this:
public void foo(final File file, final List<Line> lines)
{
// add to the List.
}
and then call it like this:
{
final List<Line> lines;
lines = new ArrayList<Line>();
foo(file, lines);
}
In my opinion, if we're talking about a public method, you should create a separate class representing a return value. When you have a separate class:
it serves as an abstraction (i.e. a Point class instead of array of two longs)
each field has a name
can be made immutable
makes evolution of API much easier (i.e. what about returning 3 instead of 2 values, changing type of some field etc.)
I would always opt for returning a new instance, instead of actually modifying a value passed in. It seems much clearer to me and favors immutability.
On the other hand, if it is an internal method, I guess any of the following might be used:
an array (new Object[] { "str", longValue })
a list (Arrays.asList(...) returns immutable list)
pair/tuple class, such as this
static inner class, with public fields
Still, I would prefer the last option, equipped with a suitable constructor. That is especially true if you find yourself returning the same tuple from more than one place.
I do wish there was a Pair<E,F> class in JDK, mostly for this reason. There is Map<K,V>.Entry, but creating an instance was always a big pain.
Now I use com.google.common.collect.Maps.immutableEntry when I need a Pair
See this RFE launched back in 1999:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4222792
I don't think the intention was to ever allow it in the Java language, if you need to return multiple values you need to encapsulate them in an object.
Using languages like Scala however you can return tuples, see:
http://www.artima.com/scalazine/articles/steps.html
You can also use Generics in Java to return a pair of objects, but that's about it AFAIK.
EDIT: Tuples
Just to add some more on this. I've previously implemented a Pair in projects because of the lack within the JDK. Link to my implementation is here:
http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9
Note, there isn't a hashcode or equals on this, which should probably be added.
I also came across this whilst doing some research into this questions which provides tuple functionality:
http://javatuple.com/
It allows you to create Pair including other types of tuples.
You cannot truly return multiple values, but you can pass objects into a method and have the method mutate those values. That is perfectly legal. Note that you cannot pass an object in and have the object itself become a different object. That is:
private void myFunc(Object a) {
a = new Object();
}
will result in temporarily and locally changing the value of a, but this will not change the value of the caller, for example, from:
Object test = new Object();
myFunc(test);
After myFunc returns, you will have the old Object and not the new one.
Legal (and often discouraged) is something like this:
private void changeDate(final Date date) {
date.setTime(1234567890L);
}
I picked Date for a reason. This is a class that people widely agree should never have been mutable. The the method above will change the internal value of any Date object that you pass to it. This kind of code is legal when it is very clear that the method will mutate or configure or modify what is being passed in.
NOTE: Generally, it's said that a method should do one these things:
Return void and mutate its incoming objects (like Collections.sort()), or
Return some computation and don't mutate incoming objects at all (like Collections.min()), or
Return a "view" of the incoming object but do not modify the incoming object (like Collections.checkedList() or Collections.singleton())
Mutate one incoming object and return it (Collections doesn't have an example, but StringBuilder.append() is a good example).
Methods that mutate incoming objects and return a separate return value are often doing too many things.
There are certainly methods that modify an object passed in as a parameter (see java.io.Reader.read(byte[] buffer) as an example, but I have not seen parameters used as an alternative for a return value, especially with multiple parameters. It may technically work, but it is nonstandard.
It's not generally considered terribly good practice, but there are very occasional cases in the JDK where this is done. Look at the 'biasRet' parameter of View.getNextVisualPositionFrom() and related methods, for example: it's actually a one-dimensional array that gets filled with an "extra return value".
So why do this? Well, just to save you having to create an extra class definition for the "occasional extra return value". It's messy, inelegant, bad design, non-object-oriented, blah blah. And we've all done it from time to time...
Generally what Eddie said, but I'd add one more:
Mutate one of the incoming objects, and return a status code. This should generally only be used for arguments that are explicitly buffers, like Reader.read(char[] cbuf).
I had a Result object that cascades through a series of validating void methods as a method parameter. Each of these validating void methods would mutate the result parameter object to add the result of the validation.
But this is impossible to test because now I cannot stub the void method to return a stub value for the validation in the Result object.
So, from a testing perspective it appears that one should favor returning a object instead of mutating a method parameter.
What exactly does immutable mean - that is, what are the consequences of an object being mutable or immutable? In particular, why are Java's Strings immutable?
My understanding is that the StringBuilder type is something like a mutable equivalent to String. When would I use StringBuilder rather than String, and vice-versa?
Immutable means that once the constructor for an object has completed execution that instance can't be altered.
This is useful as it means you can pass references to the object around, without worrying that someone else is going to change its contents. Especially when dealing with concurrency, there are no locking issues with objects that never change
e.g.
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo doesn't have to worry that the caller to getValue() might change the text in the string.
If you imagine a similar class to Foo, but with a StringBuilder rather than a String as a member, you can see that a caller to getValue() would be able to alter the StringBuilder attribute of a Foo instance.
Also beware of the different kinds of immutability you might find: Eric Lippert wrote a blog article about this. Basically you can have objects whose interface is immutable but behind the scenes actual mutables private state (and therefore can't be shared safely between threads).
An immutable object is an object where the internal fields (or at least, all the internal fields that affect its external behavior) cannot be changed.
There are a lot of advantages to immutable strings:
Performance: Take the following operation:
String substring = fullstring.substring(x,y);
The underlying C for the substring() method is probably something like this:
// Assume string is stored like this:
struct String { char* characters; unsigned int length; };
// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
struct String* out = malloc(sizeof(struct String));
out->characters = in->characters + begin;
out->length = end - begin;
return out;
}
Note that none of the characters have to be copied! If the String object were mutable (the characters could change later) then you would have to copy all the characters, otherwise changes to characters in the substring would be reflected in the other string later.
Concurrency: If the internal structure of an immutable object is valid, it will always be valid. There's no chance that different threads can create an invalid state within that object. Hence, immutable objects are Thread Safe.
Garbage collection: It's much easier for the garbage collector to make logical decisions about immutable objects.
However, there are also downsides to immutability:
Performance: Wait, I thought you said performance was an upside of immutability! Well, it is sometimes, but not always. Take the following code:
foo = foo.substring(0,4) + "a" + foo.substring(5); // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder
The two lines both replace the fourth character with the letter "a". Not only is the second piece of code more readable, it's faster. Look at how you would have to do the underlying code for foo. The substrings are easy, but now because there's already a character at space five and something else might be referencing foo, you can't just change it; you have to copy the whole string (of course some of this functionality is abstracted into functions in the real underlying C, but the point here is to show the code that gets executed all in one place).
struct String* concatenate(struct String* first, struct String* second)
{
struct String* new = malloc(sizeof(struct String));
new->length = first->length + second->length;
new->characters = malloc(new->length);
int i;
for(i = 0; i < first->length; i++)
new->characters[i] = first->characters[i];
for(; i - first->length < second->length; i++)
new->characters[i] = second->characters[i - first->length];
return new;
}
// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));
Note that concatenate gets called twice meaning that the entire string has to be looped through! Compare this to the C code for the bar operation:
bar->characters[4] = 'a';
The mutable string operation is obviously much faster.
In Conclusion: In most cases, you want an immutable string. But if you need to do a lot of appending and inserting into a string, you need the mutability for speed. If you want the concurrency safety and garbage collection benefits with it the key is to keep your mutable objects local to a method:
// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
StringBuilder mutable;
boolean first = true;
for(int i = 0; i < strings.length; i++)
{
if(first) first = false;
else mutable.append(separator);
mutable.append(strings[i]);
}
return mutable.toString();
}
Since the mutable object is a local reference, you don't have to worry about concurrency safety (only one thread ever touches it). And since it isn't referenced anywhere else, it is only allocated on the stack, so it is deallocated as soon as the function call is finished (you don't have to worry about garbage collection). And you get all the performance benefits of both mutability and immutability.
Actually String is not immutable if you use the wikipedia definition suggested above.
String's state does change post construction. Take a look at the hashcode() method. String caches the hashcode value in a local field but does not calculate it until the first call of hashcode(). This lazy evaluation of hashcode places String in an interesting position as an immutable object whose state changes, but it cannot be observed to have changed without using reflection.
So maybe the definition of immutable should be an object that cannot be observed to have changed.
If the state changes in an immutable object after it has been created but no-one can see it (without reflection) is the object still immutable?
Immutable objects are objects that can't be changed programmatically. They're especially good for multi-threaded environments or other environments where more than one process is able to alter (mutate) the values in an object.
Just to clarify, however, StringBuilder is actually a mutable object, not an immutable one. A regular java String is immutable (meaning that once it's been created you cannot change the underlying string without changing the object).
For example, let's say that I have a class called ColoredString that has a String value and a String color:
public class ColoredString {
private String color;
private String string;
public ColoredString(String color, String string) {
this.color = color;
this.string = string;
}
public String getColor() { return this.color; }
public String getString() { return this.string; }
public void setColor(String newColor) {
this.color = newColor;
}
}
In this example, the ColoredString is said to be mutable because you can change (mutate) one of its key properties without creating a new ColoredString class. The reason why this may be bad is, for example, let's say you have a GUI application which has multiple threads and you are using ColoredStrings to print data to the window. If you have an instance of ColoredString which was created as
new ColoredString("Blue", "This is a blue string!");
Then you would expect the string to always be "Blue". If another thread, however, got ahold of this instance and called
blueString.setColor("Red");
You would suddenly, and probably unexpectedly, now have a "Red" string when you wanted a "Blue" one. Because of this, immutable objects are almost always preferred when passing instances of objects around. When you have a case where mutable objects are really necessary, then you would typically guard the objet by only passing copies out from your specific field of control.
To recap, in Java, java.lang.String is an immutable object (it cannot be changed once it's created) and java.lang.StringBuilder is a mutable object because it can be changed without creating a new instance.
In large applications its common for string literals to occupy large bits of memory. So to efficiently handle the memory, the JVM allocates an area called "String constant pool".(Note that in memory even an unreferenced String carries around a char[], an int for its length, and another for its hashCode. For a number, by contrast, a maximum of eight immediate bytes is required)
When complier comes across a String literal it checks the pool to see if there is an identical literal already present. And if one is found, the reference to the new literal is directed to the existing String, and no new 'String literal object' is created(the existing String simply gets an additional reference).
Hence : String mutability saves memory...
But when any of the variables change value, Actually - it's only their reference that's changed, not the value in memory(hence it will not affect the other variables referencing it) as seen below....
String s1 = "Old string";
//s1 variable, refers to string in memory
reference | MEMORY |
variables | |
[s1] --------------->| "Old String" |
String s2 = s1;
//s2 refers to same string as s1
| |
[s1] --------------->| "Old String" |
[s2] ------------------------^
s1 = "New String";
//s1 deletes reference to old string and points to the newly created one
[s1] -----|--------->| "New String" |
| | |
|~~~~~~~~~X| "Old String" |
[s2] ------------------------^
The original string 'in memory' didn't change, but the
reference variable was changed so that it refers to the new string.
And if we didn't have s2, "Old String" would still be in the memory but
we'll not be able to access it...
"immutable" means you cannot change value. If you have an instance of String class, any method you call which seems to modify the value, will actually create another String.
String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"
To preserve changes you should do something like this
foo = foo.sustring(3);
Immutable vs mutable can be funny when you work with collections. Think about what will happen if you use mutable object as a key for map and then change the value (tip: think about equals and hashCode).
java.time
It might be a bit late but in order to understand what an immutable object is, consider the following example from the new Java 8 Date and Time API (java.time). As you probably know all date objects from Java 8 are immutable so in the following example
LocalDate date = LocalDate.of(2014, 3, 18);
date.plusYears(2);
System.out.println(date);
Output:
2014-03-18
This prints the same year as the initial date because the plusYears(2) returns a new object so the old date is still unchanged because it's an immutable object. Once created you cannot further modify it and the date variable still points to it.
So, that code example should capture and use the new object instantiated and returned by that call to plusYears.
LocalDate date = LocalDate.of(2014, 3, 18);
LocalDate dateAfterTwoYears = date.plusYears(2);
date.toString()… 2014-03-18
dateAfterTwoYears.toString()… 2016-03-18
I really like the explaination from SCJP Sun Certified Programmer for Java 5 Study Guide.
To make Java more memory efficient, the JVM sets aside a special area of memory called the "String constant pool." When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created.
Objects which are immutable can not have their state changed after they have been created.
There are three main reasons to use immutable objects whenever you can, all of which will help to reduce the number of bugs you introduce in your code:
It is much easier to reason about how your program works when you know that an object's state cannot be changed by another method
Immutable objects are automatically thread safe (assuming they are published safely) so will never be the cause of those hard-to-pin-down multithreading bugs
Immutable objects will always have the same Hash code, so they can be used as the keys in a HashMap (or similar). If the hash code of an element in a hash table was to change, the table entry would then effectively be lost, since attempts to find it in the table would end up looking in the wrong place. This is the main reason that String objects are immutable - they are frequently used as HashMap keys.
There are also some other optimisations you might be able to make in code when you know that the state of an object is immutable - caching the calculated hash, for example - but these are optimisations and therefore not nearly so interesting.
One meaning has to do with how the value is stored in the computer, For a .Net string for example, it means that the string in memory cannot be changed, When you think you're changing it, you are in fact creating a new string in memory and pointing the existing variable (which is just a pointer to the actual collection of characters somewhere else) to the new string.
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
s1="Hi" : an object s1 was created with "Hi" value in it.
s2=s1 : an object s2 is created with reference to s1 object.
s1="Bye" : the previous s1 object's value doesn't change because s1 has String type and String type is an immutable type, instead compiler create a new String object with "Bye" value and s1 referenced to it. here when we print s2 value, the result will be "Hi" not "Bye" because s2 referenced to previous s1 object which had "Hi" value.
Immutable means that once the object is created, non of its members will change. String is immutable since you can not change its content.
For example:
String s1 = " abc ";
String s2 = s1.trim();
In the code above, the string s1 did not change, another object (s2) was created using s1.
Immutable simply mean unchangeable or unmodifiable. Once string object is created its data or state can't be changed
Consider bellow example,
class Testimmutablestring{
public static void main(String args[]){
String s="Future";
s.concat(" World");//concat() method appends the string at the end
System.out.println(s);//will print Future because strings are immutable objects
}
}
Let's get idea considering bellow diagram,
In this diagram, you can see new object created as "Future World". But not change "Future".Because String is immutable. s, still refer to "Future". If you need to call "Future World",
String s="Future";
s=s.concat(" World");
System.out.println(s);//print Future World
Why are string objects immutable in java?
Because Java uses the concept of string literal. Suppose there are 5 reference variables, all refers to one object "Future".If one reference variable changes the value of the object, it will be affected to all the reference variables. That is why string objects are immutable in java.
Once instanciated, cannot be altered. Consider a class that an instance of might be used as the key for a hashtable or similar. Check out Java best practices.
As the accepted answer doesn't answer all the questions. I'm forced to give an answer after 11 years and 6 months.
Can somebody clarify what is meant by immutable?
Hope you meant immutable object (because we could think about immutable reference).
An object is immutable: iff once created, they always represent the same value (doesn't have any method that change the value).
Why is a String immutable?
Respect the above definition which could be checked by looking into the Sting.java source code.
What are the advantages/disadvantages of the immutable objects?
immutable types are :
safer from bugs.
easier to understand.
and more ready for change.
Why should a mutable object such as StringBuilder be preferred over String and vice-verse?
Narrowing the question Why do we need the mutable StringBuilder in programming?
A common use for it is to concatenate a large number of strings together, like this:
String s = "";
for (int i = 0; i < n; ++i) {
s = s + n;
}
Using immutable strings, this makes a lot of temporary copies — the first number of the string ("0") is actually copied n times in the course of building up the final string, the second number is copied n-1 times, and so on. It actually costs O(n2) time just to do all that copying, even though we only concatenated n elements.
StringBuilder is designed to minimize this copying. It uses a simple but clever internal data structure to avoid doing any copying at all until the very end, when you ask for the final String with a toString() call:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
sb.append(String.valueOf(n));
}
String s = sb.toString();
Getting good performance is one reason why we use mutable objects. Another is convenient sharing: two parts of your program can communicate more conveniently by sharing a common mutable data structure.
More could be found here : https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types
Immutable Objects
An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.
Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.
Programmers are often reluctant to employ immutable objects, because they worry about the cost of creating a new object as opposed to updating an object in place. The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.
The following subsections take a class whose instances are mutable and derives a class with immutable instances from it. In so doing, they give general rules for this kind of conversion and demonstrate some of the advantages of immutable objects.
Source
An immutable object is the one you cannot modify after you create it. A typical example are string literals.
A D programming language, which becomes increasingly popular, has a notion of "immutability" through "invariant" keyword. Check this Dr.Dobb's article about it - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . It explains the problem perfectly.
Given: Class has no fields, every variable is local. littleString was created by refactoring bigString in Eclipse:
public String bigString()
{
StringBuffer bob = new StringBuffer();
this.littleString(bob);
return bob.toString();
}
private void littleString(final StringBuffer bob)
{
bob.append("Hello, I'm Bob");
}
The method littleString should not be passing the StringBuffer back, but yet is is. What kind of Black Magic goes on here? This is breaking all rules of encapsulation that I know. I'm in shock, words fail me.
littleString isn't passing the object back -- it's just using the same object. Both the local variable bob in bigString() and the parameter bob in littleString() refer to the same object, so if you change one of those objects, the changes will appear instantaneously in the other because they're both references to the same object.
The issue is that StringBuffers are mutable and have internal state associated with them. Some types of objects (such as Strings) are immutable, so you can safely pass them around as method parameters, and you know they won't ever get modified. Note that the addition of the final keyword doesn't help here -- it just makes sure that bob never gets assigned to refer to a different StringBuffer object.
It's not passing anything back. It's modifying the StringBuffer you passed a reference to. Objects in Java are not passed by value.
If you meant why does the string buffer get modified, it's because you were passing a reference to the string buffer, which allows you to call the public method append which modifies the string buffer object.
the answers above pretty much got it, except one little thing hasnt been mentioned: java lacks "const-ness", meaning you want an object to be unmodifiable.
"final" is close, but it still doesnt do the job properly. What the code snippet showed is the kind of error that can happen if you have mutable objects passed in as parameters to other methods. This can be fixed either by having immutable objects, or if there is some kind of new keyword added for deep const-ness.