Why can a final(!) StringBuffer can be appended?

M

Mize-ze

How could it be that I declare a StringBuffer to be final but when I
try to append it to something its value
changes to the appended value?

The StringBuffer is not re-created on the system (immutable right?) so
I don't understand how this "final" bits in the heap are modified

Thanks.
 
R

Robert Klemme

How could it be that I declare a StringBuffer to be final but when I
try to append it to something its value
changes to the appended value?

The StringBuffer is not re-created on the system (immutable right?) so
I don't understand how this "final" bits in the heap are modified

"final" only refers to the reference, i.e. you cannot assign another
StringBuffer to the variable. StringBuffer itself is mutable, i.e. can
be changed at any time. If you want a fixed string you need to convert
it (easiest with toString()).

Kind regards

robert
 
M

Mark

Mize-ze said:
How could it be that I declare a StringBuffer to be final but when I
try to append it to something its value
changes to the appended value?

The StringBuffer is not re-created on the system (immutable right?)

StringBuffers are mutable: its their big difference from Strings
so I don't understand how this "final" bits in the heap are modified

(One of) the meaning(s) of "final" is that the reference can't change
(so you can't change what it is by assigning a new StringBuffer to it),
but the object can, assuming it has methods that allow it to change
like StringBuffer and Java5's StringBuilder do.

HTH,
Mark
 
M

Mark Space

Robert said:
"final" only refers to the reference, i.e. you cannot assign another
StringBuffer to the variable. StringBuffer itself is mutable, i.e. can
be changed at any time. If you want a fixed string you need to convert
it (easiest with toString()).

Kind regards

robert

Or perhaps derive your own type of StringBuffer with the mutable methods
disabled.

Hmm, actually toString is probably best. You can just change the String
back to a StringBuffer at any time, yes? This seems the easiest...

Also, I've run into problems trying to change a StringBuffer when you
declare it's size on creation. If append is specifically your problem,
you could get around it by setting the StringBuffer to be the exact size
you need. Then appending will throw an exception if it's attempted.
 
O

Oliver Wong

Mark Space said:
Also, I've run into problems trying to change a StringBuffer when you
declare it's size on creation. If append is specifically your problem,
you could get around it by setting the StringBuffer to be the exact size
you need. Then appending will throw an exception if it's attempted.

Are you sure? This program:

<SSCCE>
public class StringBTest {
public static void main(String[] args) {
{
StringBuffer sb = new StringBuffer(1);
sb.append("More than 1 character.");
System.out.println(sb.toString());
}
{
StringBuilder sb = new StringBuilder(1);
sb.append("More than 1 character.");
System.out.println(sb.toString());
}
}
}
</SSCCE>

Produces this output for me:

<output>
More than 1 character.
More than 1 character.
</output>

- Oliver
 
R

Robert Klemme

Or perhaps derive your own type of StringBuffer with the mutable methods
disabled.

Not worth the effort IMHO unless you need to change often between
mutable and immutable. But in that case I'd also add a flag which
switches mutability. But since any client can set that flag...
Hmm, actually toString is probably best. You can just change the String
back to a StringBuffer at any time, yes? This seems the easiest...

Yes, although that change is less efficient because the String has to be
copied while StringBuffer.toString() creates a String that shares the
buffer. That's optimized for the typical use case where you use a SB to
construct a String.
Also, I've run into problems trying to change a StringBuffer when you
declare it's size on creation. If append is specifically your problem,
you could get around it by setting the StringBuffer to be the exact size
you need. Then appending will throw an exception if it's attempted.

Huh? Since when has a StringBuffer a size limit other than the RAM
available?

Regards

robert
 
D

Daniel Pitts

Robert said:
Not worth the effort IMHO unless you need to change often between
mutable and immutable. But in that case I'd also add a flag which
switches mutability. But since any client can set that flag...


Yes, although that change is less efficient because the String has to be
copied while StringBuffer.toString() creates a String that shares the
buffer. That's optimized for the typical use case where you use a SB to
construct a String.

Somehow I doubt that a String shares a buffer with a StringBuffer,
since StringBuffer is still mutable, and the String is not.

Double checking the API source code, I see that String makes a copy of
the portion of the Array that is passed to it from
StringBuffer.toString().

Worrying too much about converting between Strings and StringBuffers is
one of the signs of the deadly sin known as "premature optimization".
After you've created your project, see if it runs fast enough, most
times it will. If it doesn't run fast enough, run it through a
profiler, and optimize bigist time hog.

In most cases, StringBuffer is overkill anyway, String + String +
String is good enough.
 
R

Robert Klemme

Somehow I doubt that a String shares a buffer with a StringBuffer,
since StringBuffer is still mutable, and the String is not.

> Double checking the API source code, I see that String makes a copy of
> the portion of the Array that is passed to it from
> StringBuffer.toString().

They changed that in 1.5. In 1.4 it was shared. The concept is know as
"copy on write".
Worrying too much about converting between Strings and StringBuffers is
one of the signs of the deadly sin known as "premature optimization".
After you've created your project, see if it runs fast enough, most
times it will. If it doesn't run fast enough, run it through a
profiler, and optimize bigist time hog.

I was not worrying I just made a side remark to indicate a potential
issue since I do not know the app at hand - so /if/ there is an issue
that's a potential place to look.
In most cases, StringBuffer is overkill anyway, String + String +
String is good enough.

Which is translated into StringBuffer.append() - or
StringBuilder.append() on 1.5 - unless of course all strings are constants.

Regards

robert
 
C

Chris Uppal

Robert said:
They changed that in 1.5. In 1.4 it was shared. The concept is know as
"copy on write".

They didn't change it, it's the same in 1.5 as in 1.4 (and, as far as I
remember) all the previous versions too.

I haven't checked 1.6 or 1.7.

-- chris
 
R

Robert Klemme

They didn't change it, it's the same in 1.5 as in 1.4 (and, as far as I
remember) all the previous versions too.

I beg to differ. JDK 1.4.2-11 (copy on write)

StringBuffer:

public String toString() {
return new String(this);
}

final void setShared() { shared = true; }
final char[] getValue() { return value; }

String:

public String (StringBuffer buffer) {
synchronized(buffer) {
buffer.setShared();
this.value = buffer.getValue();
this.offset = 0;
this.count = buffer.length();
}
}


JDK 1.5.0-6 (always copy)

StringBuffer:

public synchronized String toString() {
return new String(value, 0, count);
}

public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
char[] v = new char[count];
System.arraycopy(value, offset, v, 0, count);
this.offset = 0;
this.count = count;
this.value = v;
}

Regards

robert
 

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,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top