tags:

views:

697

answers:

5

The method Concat() does not modify the original value. It returns a new value.
like this:

String str = "good";
str.concat("ness");
System.out.println(str);   //"good"

But some method modify the original value. Why?

In Groovy:

def languages = ["Java", "Groovy", "JRuby"]
languages.reverse()
===> [JRuby, Groovy, Java]
println languages
===> [Java, Groovy, JRuby]


languages.sort()
===> [Groovy, JRuby, Java]
println languages
===> [Groovy, JRuby, Java]
+10  A: 

String is immutable in Java. Any method that "modifies" a String must return a new instance of String.

From the Java API Specifications for the String class:

Strings are constant; their values cannot be changed after they are created.

The Java Language Specifications defines this behavior in Section 4.3.3: The Class String.


Response to the edit:

It appears that an example in Groovy has been added. (I haven't used Groovy before, so my understanding of it may not be correct.)

From what I understand from looking at the example, there seems to be a languages list that is being reverse-ed and sort-ed -- those operations themselves do not modify the String objects contained in the list, but are acting upon the list itself.

The way the list is returns a new list, or how it modifies or doesn't modify the list is not related to the behavior of the String objects themselves.

coobird
No, the point of the groovy examples seems to be that the method reverse() does not modify the object (instead, it returns a new object), whereas sort() modifies it.
@dehmann: Ah, I missed that part! Thank you for pointing that out!
coobird
@dehmann:Why the method reverse() return a new object and sort() modifies it? Is there any rule we can get if I don't see the API?
JSON
A: 

Because there are immutable and mutable classes.

String, as another answer points out, is an immutable class. Their value always stays the same once a String is created.

If you have an ArrayList<Integer> object, you can use its add function to add another Integer to the list. The add function changes the list in-place, instead of returning a new list. An ArrayList is mutable.

Response to Edit:

For your groovy example, probably its designers sat down and noticed that more often one would want a new list that contains the reversed result, and keep the old list untouched. (Why? I don't know). On the other side, they may have noticed there are more cases where you want not to have a new list which contains the sorted result. So it does its job in-place. But i don't know and haven't used groovy before, so just a guess.

In Ruby, i have heard there is a notion for this: Functions that change objects in-place have an exclamation written after them, and functions that return the result as a new object have no exclamation mark:

newObj = obj.sort(); // new sorted list is returned
obj.sort!(); // obj is sorted in-place
Johannes Schaub - litb
+3  A: 

The Java API was designed by many many different people, as such it's hard to keep everything consistent. I believe people generally accept that immutability (i.e., the internal states should not change) is a good thing now though, at least where value objects are concerned.

Another similar question would be, "why are indexes sometimes 0-based (most of the time), and somes times 1-based (JDBC)." Again, I believe it's another situation of the API being too broad, and developers of different APIs not coordinating (I could be wrong here though, if anyone knows the real reason for JDBC being 1-based, please let me know).

Jack Leow
JDBC being 1-based is really an exception, the norm is 0-based. Maybe some database API is showing through.
starblue
+2  A: 

I think you mean str.concat("ness") instead. In this particular example with Strings, no method can mutate the object because Strings are designed to be immutable. In the library, you will find many methods that mutate the state of the object (e.g. StringBuffer.replace()) and others that don't (e.g. String.replace()). You'll have to read the API carefully to determine which is the case. Ultimately, this is a choice made by the library designer, who has to consider the functionality, ease of use, and conventions associated with the package he or she is writing.

Zach Scrivena
Wouldn't it be good if there were a convention saying: If a method does not need access to internals of the object and does not change the state of the object, then it should not be a member (or should be static?) String.replace() seems to be a good example.
I agree. That would certainly make the API more consistent.
Zach Scrivena
A: 

To some extent this also has to do with programming style. Not changing the original object and creating new copies to reflect the changes is an idiom for safe programming. I believe Josh Bloch mentioned it in his book "Effective Java" (The first edition). Though I cannot remember the exact term he used for it.

In the case of String it returns a new object because String is immutable. However, across the Java API, you will see some places where the original object is changed and some places where a new object is returned. As someone pointed out earlier, it is because different people have worked on the API, and they bring their own programming styles.

On a slightly different note: keeping objects immutable adds safety to the code, and it also allows us to code in a certain way.

(new Date()).add(new Month(7)).add(new Day(4))

If every method on Date returns a new object instead of changing it's own state, then we can write such code. This makes programs very readable.

However, keeping objects immutable, may add reduce the performance of the system if we have large objects.

Parag