[jdom-interest] Text class (Modified)
Steve Odendahl
steve.odendahl at central.sun.com
Mon May 28 08:07:18 PDT 2001
Reusing the StringBuffer may not be a good idea, at least
prior to JDK1.3. Check out bug ID 4295713.
Basically, what can happen is this ...
StringBuffer reuseMe = new StringBuffer ();
// ... append lots of stuff to reuseMe, making reuseMe's
// internal char[] (for example) 5000 characters long
String longString = reuseMe.toString ();
// longString uses reuseMe's 5000 long char[], and the shared
// flag in reuseMe is set to true.
reuseMe.setLength (0);
// since reuseMe's shared flag is true, reuseMe creates a new
// internal char[] of length 5000 (in JDK1.3 this was patched
// to reset to the default length of 16 when the new length
// is 0), and the shared flag is set to false.
// ... append a little bit of stuff to reuseMe, making its
// length (for example) 3 characters
String shortString = reuseMe.toString ();
// Even though shortString is 3 characters long, it uses
// an underlying char[] of length 5000. If the reference
// to shortString is held for a long time ... :-(
I learned this from a talk given at JavaOne 2000 by Craig
Larman of Valtech.
Steve Odendahl
(Not speaking for Sun Microsystems, Inc.)
At approximately 06:51:02 PM on Sun, May 27, 2001,
Amy Lewis sent this message:
> Yah, there was just a suggestion to reuse the string buffer, instead of
> making a new one each time the value is set, so:
>
> On Sun, May 27, 2001 at 04:42:12PM -0500, Brett McLaughlin wrote:
> >OK. So now we're at:
> >
> >public class Text {
> >
> > private StringBuffer value;
>
> private StringBuffer value = new StringBuffer();
>
> > private Element parent;
> >
> > protected Text() { }
> >
> > public Text(String stringValue) {
> > value = new StringBuffer(stringValue);
>
> value.setLength(0);
> value.append(stringValue);
>
> > }
> >
> > public String getValue() {
> > return value.toString();
> > }
>
> Since the underlying abstraction is a StringBuffer, is it permissible
> to expose that for those who want to be able to use replace() et alii
> without creating a new SB then calling setValue? If so:
>
> public StringBuffer getBuffer() {
> return value;
> }
>
> The question is: would this cause inflexibility if, in future, some
> other implementation were chosen? It's easy enough, of course, to
> return new StringBuffer(getValue()), but that won't work ... if the
> semantics are to be that the returned buffer is live (changing it
> changes the owning Text). So it's presented for discussion.
>
> >
> > public void setValue(String stringValue) {
> > value = new StringBuffer(stringValue);
>
> value.setLength(0);
> value.append(stringValue);
>
> > }
>
> You might also want (for ease in copying)
>
> public void setValue(Text other)
> {
> value.setLength(0);
> value.append(other.value);
> }
>
> (ugh, needs a test for null)
>
> >
> > public void append(String stringValue) {
> > value.append(stringValue);
> > }
> >
> > public Element getParent() {
> > return parent;
> > }
> >
> > protected void setParent(Element parent) {
> > this.parent = parent;
> > }
> >
> > public String toString() {
> > return getValue();
> > }
> >
> > public int hashCode() {
> > return value.toString().hashCode();
> > }
> >
> > public Object clone() {
> > Text newText = new Text(value);
> > newText.setParent(parent);
> > }
> >
> > public boolean equals(Object ob) {
> > if (ob instanceof Text) {
> > if (((Text)ob).value.equals(value)) {
> > return true;
> > }
> > }
> > return false;
> > }
>
> I'd suggest allowing this to be polymorphic, although I'm not quite
> certain that this is the best thing to do. If you did so, then you'd
> add: else if (ob instanceof StringBuffer) { ... } else if (ob instanceof
> String) { ... }
>
> However, I dunno if this is necessarily the semantics that equals ought
> to have. So consider it for discussion only.
>
> >}
>
> Amy!
More information about the jdom-interest
mailing list