Why String is Immutable?

D

Dimitri Maziuk

Chris Smith sez:
I agree with you. Even better yet, I'm quite CERTAIN that immutability
is not what the C++ const keyword was designed for.

Applied to primitive types (using Java terminology), c++ "const" does
the same thing as Java "final". The fun starts when "const" is applied
to pointers & references on c++ side, and "final" -- to fields, methods,
and classes on Java side.

Dima
 
T

Tor Iver Wilhelmsen

Dimitri Maziuk said:
Applied to primitive types (using Java terminology), c++ "const" does
the same thing as Java "final". The fun starts when "const" is applied
to pointers & references on c++ side, and "final" -- to fields, methods,
and classes on Java side.

Yes: Java's final as applied to a field only covers one of the
multitude of uses of const in C++, e.g.

class sample {
public:
int method(const someclass * const argument) const;
}

Java's final can give you the first of these for object references, or
the second for primitives; you cannot have pointers to primitives or
non-pointer object fields so there is no need for their reverse
relationships.

And you cannot use it to declare that a member function will not
affect state, as in the third use here.
 
D

DaLoverhino

Java newbie here... so this could be a really dumb question...

String's are references, and so is MyClass, and Object, etc, etc.
If we are so worried about String's changing values underneath us, why
aren't we so worried about other references changing values underneath
us too?
 
D

Dimitri Maziuk

Tor Iver Wilhelmsen sez:
Yes: Java's final as applied to a field only covers one of the
multitude of uses of const in C++, e.g.

[ snipped ]
And you cannot use it to declare that a member function will not
affect state, as in the third use here.

Actually, it's the second use of const (that I didn't mention, probably
because it's the one relevant to Subject ;) -- a guarantee that function
won't modify object's state (const method) or its (const) parameter.

So in C++ you can tell if object is immutable from the interface: if
there's no direct access to fields and all methods are const, it is
immutable.

In Java, OTOH, all you can do is hope that class authors wrote the
proper Javadoc. (Authors of Integer in 1.4.2, for one example, did not:
there's no "mutable" substring anywhere on the page.) The API doesn't
tell you squat: javac will happily compile

public int getValue() { return ++val; }

(whereas CC will NOT compile "int foo::getValue() const { return ++val; }",
of course).

I can't think of the "multitude of uses" of const -- there's read-only
variables, non-mutator methods, and const parameters (so you can pass
large structures by pointer/reference and have them read-only, too; note
that you can't do that in Java -- all objects parameters are by-reference).

The rest is pointer-related confusion: pointer/reference itself is a value
which may be const, plus the value it points to may be const. Java's way of
dealing with pointers is to pretend they don't exist, which leads to all sorts
of fun things including the need for immutable objects. (Consider, for example
"Foo *const foo = new Foo();" vs. "final Foo foo = new Foo()": these
do the same -- not very useful -- thing. The useful thing is
"Foo const *foo", but since There Are No Pointers(tm), in Java you can only
declare "foo" itself "final", not the object behind it.)

Dima
 
O

Oliver Wong

DaLoverhino said:
String's are references, and so is MyClass, and Object, etc, etc.
If we are so worried about String's changing values underneath us, why
aren't we so worried about other references changing values underneath
us too?

You can control visibility of a particular reference, but not of objects
floating around in memory.

For example, if you declare a local variable inside a method, the only
thing that can modify what that variable points to is code inside the same
method. Assuming your code is no longer than 1 or 2 screenfulls, you don't
have to read much to know everything that's happening to the variable
itself.

However, anyone who has a reference to an object in memory can call the
methods on that object, possibly affecting its state.

As an example, consider this a method "void foo(Object bar)". Foo has
received a reference to an object which it stores in its variable bar. No
one can mess with what bar points to except the method itself; that is to
say, if foo never assigns anything else to bar, you can be confident that
bar will always point to the same object. But if bar points to a mutable
object, then anyone who has a reference to bar can change its state. And you
don't know who has a reference to bar. The method that called foo certainly
has a reference (how else could it have passed that reference to foo?), but
where did that method get its reference from? Perhaps it got it from yet
another method. And perhaps that method got it from a publically visible
field (meaning anyone at all can have access to the object).

A typical scenario where this issue comes up is when you have a
collection of something (e.g bank account information), and you want give
someone read-access to it, but not to give any write access. If you just
pass a vector of objects (even if it's a vector of immutable objects), then
client code could take that Vector and add or remove whatever it wants.
Since your code and the client code are sharing the same instance of the
Vector object, and changes the client makes will show up in your data!

- Oliver
 
R

Roedy Green

String's are references, and so is MyClass, and Object, etc, etc.
If we are so worried about String's changing values underneath us, why
aren't we so worried about other references changing values underneath
us too?

The os deals primarily in ints and Strings. These it can't have
changing under its nose while it is working on them. There must be no
way of confusing an OS by changing something that it is working on. So
java invented the immutable string and pass by value. Once you hand
something to the os, you CAN'T bugger it up even if you try.

Little else is crucial to the OS or the JVM working properly.
 
T

Tim Tyler

Roedy Green said:
see http://mindprod.com/jgloss/immutable.html

We have done it many times before.

On that page it states:

``Advantages of Immutablitiy [sp] [...]

``* You can share duplicates by pointing them to a single instance. You
need only one copy, e.g. String interning.
* You can create substrings without copying. Immutability is the secret
behind Java's very fast substring implementation.''

Is that correct? It seems to me that a mutable string could exhibit
roughly the same performance as an immutable string simply by using
a copy-on-modification paradigm - so it doesn't seem very fair to list
this these as advantages of immutability.

I think this consideration also deals with the hashtable issue. If
you pass a string to a hashtable, it takes a copy of it. There's no
performance or memory overhead to doing that - since it just marks the
string as shared.

That leaves concurrency-related issues.
 
R

Roedy Green

* You can create substrings without copying. Immutability is the secret
behind Java's very fast substring implementation.''

Is that correct? It seems to me that a mutable string could exhibit
roughly the same performance as an immutable string simply by using
a copy-on-modification paradigm - so it doesn't seem very fair to list
this these as advantages of immutability.

Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. I don't think you would want
that logical tie.
 
O

Oliver Wong

Roedy Green said:
Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. I don't think you would want
that logical tie.

I think changing the length or value falls under Tim's definition of
"modification", so that at that point, it would be copied, so that changes
to the original do not affect the substring.

- Oliver
 
T

Tor Iver Wilhelmsen

Tim Tyler said:
Is that correct? It seems to me that a mutable string could exhibit
roughly the same performance as an immutable string simply by using
a copy-on-modification paradigm - so it doesn't seem very fair to list
this these as advantages of immutability.

In which case StringBuffer _is_ your desired mutable String. :)
 
T

Thomas Hawtin

Roedy said:
Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. I don't think you would want
that logical tie.

A substring String doesn't keep a reference to the old String, so the
value of offset and length is irrelevant. All that is necessary is for
the char[] object to be unchanging.

If you changed a character of the old string, a new char[] would be
created. Clearly the performance of this would be terrible - not a long
way from doing the same for an immutable string, if it was a directly
supported operation.

Tom Hawtin
 
T

Tim Tyler

Roedy Green said:
or quoted :
* You can create substrings without copying. Immutability is the secret
behind Java's very fast substring implementation.''

Is that correct? It seems to me that a mutable string could exhibit
roughly the same performance as an immutable string simply by using
a copy-on-modification paradigm - so it doesn't seem very fair to list
this these as advantages of immutability.

Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. [...]

No. Copy on write is a fairly straightforwards implementation approach -
and IIRC, StringBuffer uses it once you have toString'd it. There is no
issue along the lines you mention. If you modify a shared String, it
is first duplicated.
 
T

Tim Tyler

Thomas Hawtin said:
Roedy said:
Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. I don't think you would want
that logical tie.

A substring String doesn't keep a reference to the old String, so the
value of offset and length is irrelevant. All that is necessary is for
the char[] object to be unchanging.

If you changed a character of the old string, a new char[] would be
created. Clearly the performance of this would be terrible - not a long
way from doing the same for an immutable string, if it was a directly
supported operation.

The implementation is not much difference performance wise from the
current approach.

The claim was that using immutable strings had performance
benefits in allowing rapid substring operation.

Since mutable strings can use much the same trick - with a copy-on-write
paradigm - I find it hard to see the resulting performance advantage as a
benefit of immutability.
 
T

Tim Tyler

Tor Iver Wilhelmsen said:
In which case StringBuffer _is_ your desired mutable String. :)

Except that you can't use quotes to create a StringBuffer -
or plus to concatenate them - StringBuffers have no syntax sugar.
 
S

Stefan Ram

Tim Tyler said:
Except that you can't use quotes to create a StringBuffer -
or plus to concatenate them - StringBuffers have no syntax sugar.

Well, in a sense, sometimes, they have:

cat Test.java

public class Test
{ static java.lang.String ClientData = "";
static void example( final java.lang.String tmp )
{ ClientData=ClientData+tmp+"\r\n"; }}

javac Test.java

javap -C Test.java

Compiled from "Test.java"
public class Test extends java.lang.Object{
static java.lang.String ClientData;

public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

static void example(java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: getstatic #4; //Field ClientData:Ljava/lang/String;
10: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
13: aload_0
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: ldc #6; //String \r\n
19: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: putstatic #4; //Field ClientData:Ljava/lang/String;
28: return

static {};
Code:
0: ldc #8; //String
2: putstatic #4; //Field ClientData:Ljava/lang/String;
5: return

}
 
M

Mark Thornton

Tim said:
Roedy Green said:
or quoted :
* You can create substrings without copying. Immutability is the secret
behind Java's very fast substring implementation.''

Is that correct? It seems to me that a mutable string could exhibit
roughly the same performance as an immutable string simply by using
a copy-on-modification paradigm - so it doesn't seem very fair to list
this these as advantages of immutability.

Let's say string were mutable and you took a substring by creating a
reference into the base string. Then if someone changed the length
or value of the original string your substring would change too and
could even become invalid in mid flight. [...]


No. Copy on write is a fairly straightforwards implementation approach -
and IIRC, StringBuffer uses it once you have toString'd it. There is no
issue along the lines you mention. If you modify a shared String, it
is first duplicated.

It used to do this, but I believe it doesn't any more. It caused too
many problems.

Mark Thornton
 
T

Tim Tyler

Vova Reznik said:
Bharath Ganesh wrote:

Why not have discussion about why Double is Immutable? :)
Why replacing any digit in number will create another number (not
necessary different)?

In the case of double, the syntax sugar of operators can be applied
to the mutable version - and not to the immutable version.

With Strings it's the other way around - it's the mutable version
that is awkward to use; and it's the immutable version that has all
the syntax sugar.
 
T

Thomas Hawtin

Mark said:
It used to do this, but I believe it doesn't any more. It caused too
many problems.

Yup, before 5.0 StringBuffer would share its buffer. It was a bit tricky
with respect to serialisation, but the real problem was that Strings
were never entirely immutable. You can create an object in one thread.
Unsafely transfer it to another, where you may read some half-way
constructed version.

From 5.0 the new final field semantics mean that String really can be
immutable. However, it does require that the char[] has to be created
within the constructor and not taken from a pre-existing source.

Tom Hawtin
 
R

Roedy Green

I think changing the length or value falls under Tim's definition of
"modification", so that at that point, it would be copied, so that changes
to the original do not affect the substring.

That inhibits any sort of optimisation on the read side since the
underlying substring address could change at any instant. That also
adds overhead to every potential change to check for dependent
substrings.

I could see you inventing a subStringBuilder, but I think you would
still want the various benefits of an immutable String.
 
T

Tor Iver Wilhelmsen

Tim Tyler said:
Except that you can't use quotes to create a StringBuffer

StringBuffer b = new StringBuffer("Why not? This works.")
or plus to concatenate them

The String + does exactly the same as StringBuffer.append().
- StringBuffers have no syntax sugar.

Syntactic sugar is not that important.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top