      1 /*
      2  * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25
     26 package java.lang;
     27

     28 import java.util.Arrays;
     29 import jdk.internal.HotSpotIntrinsicCandidate;
     30
     31 /**
     32  * A thread-safe, mutable sequence of characters.
     33  * A string buffer is like a {@link String}, but can be modified. At any
     34  * point in time it contains some particular sequence of characters, but
     35  * the length and content of the sequence can be changed through certain
     36  * method calls.
     37  * <p>
     38  * String buffers are safe for use by multiple threads. The methods
     39  * are synchronized where necessary so that all the operations on any
     40  * particular instance behave as if they occur in some serial order
     41  * that is consistent with the order of the method calls made by each of
     42  * the individual threads involved.
     43  * <p>
     44  * The principal operations on a {@code StringBuffer} are the
     45  * {@code append} and {@code insert} methods, which are
     46  * overloaded so as to accept data of any type. Each effectively
     47  * converts a given datum to a string and then appends or inserts the
     48  * characters of that string to the string buffer. The
     49  * {@code append} method always adds these characters at the end
     50  * of the buffer; the {@code insert} method adds the characters at
     51  * a specified point.
     52  * <p>
     53  * For example, if {@code z} refers to a string buffer object
     54  * whose current contents are {@code "start"}, then
     55  * the method call {@code z.append("le")} would cause the string
     56  * buffer to contain {@code "startle"}, whereas
     57  * {@code z.insert(4, "le")} would alter the string buffer to
     58  * contain {@code "starlet"}.
     59  * <p>
     60  * In general, if sb refers to an instance of a {@code StringBuffer},
     61  * then {@code sb.append(x)} has the same effect as
     62  * {@code sb.insert(sb.length(), x)}.
     63  * <p>
     64  * Whenever an operation occurs involving a source sequence (such as
     65  * appending or inserting from a source sequence), this class synchronizes
     66  * only on the string buffer performing the operation, not on the source.
     67  * Note that while {@code StringBuffer} is designed to be safe to use
     68  * concurrently from multiple threads, if the constructor or the
     69  * {@code append} or {@code insert} operation is passed a source sequence
     70  * that is shared across threads, the calling code must ensure
     71  * that the operation has a consistent and unchanging view of the source
     72  * sequence for the duration of the operation.
     73  * This could be satisfied by the caller holding a lock during the
     74  * operation's call, by using an immutable source sequence, or by not
     75  * sharing the source sequence across threads.
     76  * <p>
     77  * Every string buffer has a capacity. As long as the length of the
     78  * character sequence contained in the string buffer does not exceed
     79  * the capacity, it is not necessary to allocate a new internal
     80  * buffer array. If the internal buffer overflows, it is
     81  * automatically made larger.
     82  * <p>
     83  * Unless otherwise noted, passing a {@code null} argument to a constructor
     84  * or method in this class will cause a {@link NullPointerException} to be
     85  * thrown.
     86  * <p>
     87  * As of  release JDK 5, this class has been supplemented with an equivalent
     88  * class designed for use by a single thread, {@link StringBuilder}.  The
     89  * {@code StringBuilder} class should generally be used in preference to
     90  * this one, as it supports all of the same operations but it is faster, as
     91  * it performs no synchronization.
     92  *
     93  * @apiNote
     94  * {@code StringBuffer} implements {@code Comparable} but does not override
     95  * {@link Object#equals equals}. Thus, the natural ordering of {@code StringBuffer}
     96  * is inconsistent with equals. Care should be exercised if {@code StringBuffer}
     97  * objects are used as keys in a {@code SortedMap} or elements in a {@code SortedSet}.
     98  * See {@link Comparable}, {@link java.util.SortedMap SortedMap}, or
     99  * {@link java.util.SortedSet SortedSet} for more information.
    100  *
    101  * @author      Arthur van Hoff
    102  * @see     java.lang.StringBuilder
    103  * @see     java.lang.String
    104  * @since   1.0
    105  */
    106  public final class StringBuffer
    107     extends AbstractStringBuilder
    108     implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
    109 {
    110
    111     /**
    112      * A cache of the last value returned by toString. Cleared
    113      * whenever the StringBuffer is modified.
    114      */
    115     private transient String toStringCache;
    116
    117     /** use serialVersionUID from JDK 1.0.2 for interoperability */
    118     @java.io.Serial
    119     static final long serialVersionUID = 3388685877147921107L;
    120
    121     /**
    122      * Constructs a string buffer with no characters in it and an
    123      * initial capacity of 16 characters.
    124      */
    125     @HotSpotIntrinsicCandidate
    126     public StringBuffer() {
    127         super(16);
    128     }
    129
    130     /**
    131      * Constructs a string buffer with no characters in it and
    132      * the specified initial capacity.
    133      *
    134      * @param      capacity  the initial capacity.
    135      * @throws     NegativeArraySizeException  if the {@code capacity}
    136      *             argument is less than {@code 0}.
    137      */
    138     @HotSpotIntrinsicCandidate
    139     public StringBuffer(int capacity) {
    140         super(capacity);
    141     }
    142
    143     /**
    144      * Constructs a string buffer initialized to the contents of the
    145      * specified string. The initial capacity of the string buffer is
    146      * {@code 16} plus the length of the string argument.
    147      *
    148      * @param   str   the initial contents of the buffer.
    149      */
    150     @HotSpotIntrinsicCandidate
    151     public StringBuffer(String str) {
    152         super(str);
    153     }
    154
    155     /**
    156      * Constructs a string buffer that contains the same characters
    157      * as the specified {@code CharSequence}. The initial capacity of
    158      * the string buffer is {@code 16} plus the length of the
    159      * {@code CharSequence} argument.
    160      *
    161      * @param      seq   the sequence to copy.
    162      * @since 1.5
    163      */
    164     public StringBuffer(CharSequence seq) {
    165         super(seq);
    166     }
    167
    168     /**
    169      * Compares two {@code StringBuffer} instances lexicographically. This method
    170      * follows the same rules for lexicographical comparison as defined in the
    171      * {@linkplain java.lang.CharSequence#compare(java.lang.CharSequence,
    172      * java.lang.CharSequence)  CharSequence.compare(this, another)} method.
    173      *
    174      * <p>
    175      * For finer-grained, locale-sensitive String comparison, refer to
    176      * {@link java.text.Collator}.
    177      *
    178      * @implNote
    179      * This method synchronizes on {@code this}, the current object, but not
    180      * {@code StringBuffer another} with which {@code this StringBuffer} is compared.
    181      *
    182      * @param another the {@code StringBuffer} to be compared with
    183      *
    184      * @return  the value {@code 0} if this {@code StringBuffer} contains the same
    185      * character sequence as that of the argument {@code StringBuffer}; a negative integer
    186      * if this {@code StringBuffer} is lexicographically less than the
    187      * {@code StringBuffer} argument; or a positive integer if this {@code StringBuffer}
    188      * is lexicographically greater than the {@code StringBuffer} argument.
    189      *
    190      * @since 11
    191      */
    192     @Override
    193     public synchronized int compareTo(StringBuffer another) {
    194         return super.compareTo(another);
    195     }
    196
    197     @Override
    198     public synchronized int length() {
    199         return count;
    200     }
    201
    202     @Override
    203     public synchronized int capacity() {
    204         return super.capacity();
    205     }
    206
    207
    208     @Override
    209     public synchronized void ensureCapacity(int minimumCapacity) {
    210         super.ensureCapacity(minimumCapacity);
    211     }
    212
    213     /**
    214      * @since      1.5
    215      */
    216     @Override
    217     public synchronized void trimToSize() {
    218         super.trimToSize();
    219     }
    220
    221     /**
    222      * @throws IndexOutOfBoundsException {@inheritDoc}
    223      * @see        #length()
    224      */
    225     @Override
    226     public synchronized void setLength(int newLength) {
    227         toStringCache = null;
    228         super.setLength(newLength);
    229     }
    230
    231     /**
    232      * @throws IndexOutOfBoundsException {@inheritDoc}
    233      * @see        #length()
    234      */
    235     @Override
    236     public synchronized char charAt(int index) {
    237         return super.charAt(index);
    238     }
    239
    240     /**
    241      * @throws IndexOutOfBoundsException {@inheritDoc}
    242      * @since      1.5
    243      */
    244     @Override
    245     public synchronized int codePointAt(int index) {
    246         return super.codePointAt(index);
    247     }
    248
    249     /**
    250      * @throws IndexOutOfBoundsException {@inheritDoc}
    251      * @since     1.5
    252      */
    253     @Override
    254     public synchronized int codePointBefore(int index) {
    255         return super.codePointBefore(index);
    256     }
    257
    258     /**
    259      * @throws IndexOutOfBoundsException {@inheritDoc}
    260      * @since     1.5
    261      */
    262     @Override
    263     public synchronized int codePointCount(int beginIndex, int endIndex) {
    264         return super.codePointCount(beginIndex, endIndex);
    265     }
    266
    267     /**
    268      * @throws IndexOutOfBoundsException {@inheritDoc}
    269      * @since     1.5
    270      */
    271     @Override
    272     public synchronized int offsetByCodePoints(int index, int codePointOffset) {
    273         return super.offsetByCodePoints(index, codePointOffset);
    274     }
    275
    276     /**
    277      * @throws IndexOutOfBoundsException {@inheritDoc}
    278      */
    279     @Override
    280     public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
    281                                       int dstBegin)
    282     {
    283         super.getChars(srcBegin, srcEnd, dst, dstBegin);
    284     }
    285
    286     /**
    287      * @throws IndexOutOfBoundsException {@inheritDoc}
    288      * @see        #length()
    289      */
    290     @Override
    291     public synchronized void setCharAt(int index, char ch) {
    292         toStringCache = null;
    293         super.setCharAt(index, ch);
    294     }
    295
    296     @Override
    297     public synchronized StringBuffer append(Object obj) {
    298         toStringCache = null;
    299         super.append(String.valueOf(obj));
    300         return this;
    301     }
    302
    303     @Override
    304     @HotSpotIntrinsicCandidate
    305     public synchronized StringBuffer append(String str) {
    306         toStringCache = null;
    307         super.append(str);
    308         return this;
    309     }
    310
    311     /**
    312      * Appends the specified {@code StringBuffer} to this sequence.
    313      * <p>
    314      * The characters of the {@code StringBuffer} argument are appended,
    315      * in order, to the contents of this {@code StringBuffer}, increasing the
    316      * length of this {@code StringBuffer} by the length of the argument.
    317      * If {@code sb} is {@code null}, then the four characters
    318      * {@code "null"} are appended to this {@code StringBuffer}.
    319      * <p>
    320      * Let <i>n</i> be the length of the old character sequence, the one
    321      * contained in the {@code StringBuffer} just prior to execution of the
    322      * {@code append} method. Then the character at index <i>k</i> in
    323      * the new character sequence is equal to the character at index <i>k</i>
    324      * in the old character sequence, if <i>k</i> is less than <i>n</i>;
    325      * otherwise, it is equal to the character at index <i>k-n</i> in the
    326      * argument {@code sb}.
    327      * <p>
    328      * This method synchronizes on {@code this}, the destination
    329      * object, but does not synchronize on the source ({@code sb}).
    330      *
    331      * @param   sb   the {@code StringBuffer} to append.
    332      * @return  a reference to this object.
    333      * @since 1.4
    334      */
    335     public synchronized StringBuffer append(StringBuffer sb) {
    336         toStringCache = null;
    337         super.append(sb);
    338         return this;
    339     }
    340
    341     /**
    342      * @since 1.8
    343      */
    344     @Override
    345     synchronized StringBuffer append(AbstractStringBuilder asb) {
    346         toStringCache = null;
    347         super.append(asb);
    348         return this;
    349     }
    350
    351     /**
    352      * Appends the specified {@code CharSequence} to this
    353      * sequence.
    354      * <p>
    355      * The characters of the {@code CharSequence} argument are appended,
    356      * in order, increasing the length of this sequence by the length of the
    357      * argument.
    358      *
    359      * <p>The result of this method is exactly the same as if it were an
    360      * invocation of this.append(s, 0, s.length());
    361      *
    362      * <p>This method synchronizes on {@code this}, the destination
    363      * object, but does not synchronize on the source ({@code s}).
    364      *
    365      * <p>If {@code s} is {@code null}, then the four characters
    366      * {@code "null"} are appended.
    367      *
    368      * @param   s the {@code CharSequence} to append.
    369      * @return  a reference to this object.
    370      * @since 1.5
    371      */
    372     @Override
    373     public synchronized StringBuffer append(CharSequence s) {
    374         toStringCache = null;
    375         super.append(s);
    376         return this;
    377     }
    378
    379     /**
    380      * @throws IndexOutOfBoundsException {@inheritDoc}
    381      * @since      1.5
    382      */
    383     @Override
    384     public synchronized StringBuffer append(CharSequence s, int start, int end)
    385     {
    386         toStringCache = null;
    387         super.append(s, start, end);
    388         return this;
    389     }
    390
    391     @Override
    392     public synchronized StringBuffer append(char[] str) {
    393         toStringCache = null;
    394         super.append(str);
    395         return this;
    396     }
    397
    398     /**
    399      * @throws IndexOutOfBoundsException {@inheritDoc}
    400      */
    401     @Override
    402     public synchronized StringBuffer append(char[] str, int offset, int len) {
    403         toStringCache = null;
    404         super.append(str, offset, len);
    405         return this;
    406     }
    407
    408     @Override
    409     public synchronized StringBuffer append(boolean b) {
    410         toStringCache = null;
    411         super.append(b);
    412         return this;
    413     }
    414
    415     @Override
    416     @HotSpotIntrinsicCandidate
    417     public synchronized StringBuffer append(char c) {
    418         toStringCache = null;
    419         super.append(c);
    420         return this;
    421     }
    422
    423     @Override
    424     @HotSpotIntrinsicCandidate
    425     public synchronized StringBuffer append(int i) {
    426         toStringCache = null;
    427         super.append(i);
    428         return this;
    429     }
    430
    431     /**
    432      * @since 1.5
    433      */
    434     @Override
    435     public synchronized StringBuffer appendCodePoint(int codePoint) {
    436         toStringCache = null;
    437         super.appendCodePoint(codePoint);
    438         return this;
    439     }
    440
    441     @Override
    442     public synchronized StringBuffer append(long lng) {
    443         toStringCache = null;
    444         super.append(lng);
    445         return this;
    446     }
    447
    448     @Override
    449     public synchronized StringBuffer append(float f) {
    450         toStringCache = null;
    451         super.append(f);
    452         return this;
    453     }
    454
    455     @Override
    456     public synchronized StringBuffer append(double d) {
    457         toStringCache = null;
    458         super.append(d);
    459         return this;
    460     }
    461
    462     /**
    463      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    464      * @since      1.2
    465      */
    466     @Override
    467     public synchronized StringBuffer delete(int start, int end) {
    468         toStringCache = null;
    469         super.delete(start, end);
    470         return this;
    471     }
    472
    473     /**
    474      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    475      * @since      1.2
    476      */
    477     @Override
    478     public synchronized StringBuffer deleteCharAt(int index) {
    479         toStringCache = null;
    480         super.deleteCharAt(index);
    481         return this;
    482     }
    483
    484     /**
    485      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    486      * @since      1.2
    487      */
    488     @Override
    489     public synchronized StringBuffer replace(int start, int end, String str) {
    490         toStringCache = null;
    491         super.replace(start, end, str);
    492         return this;
    493     }
    494
    495     /**
    496      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    497      * @since      1.2
    498      */
    499     @Override
    500     public synchronized String substring(int start) {
    501         return substring(start, count);
    502     }
    503
    504     /**
    505      * @throws IndexOutOfBoundsException {@inheritDoc}
    506      * @since      1.4
    507      */
    508     @Override
    509     public synchronized CharSequence subSequence(int start, int end) {
    510         return super.substring(start, end);
    511     }
    512
    513     /**
    514      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    515      * @since      1.2
    516      */
    517     @Override
    518     public synchronized String substring(int start, int end) {
    519         return super.substring(start, end);
    520     }
    521
    522     /**
    523      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    524      * @since      1.2
    525      */
    526     @Override
    527     public synchronized StringBuffer insert(int index, char[] str, int offset,
    528                                             int len)
    529     {
    530         toStringCache = null;
    531         super.insert(index, str, offset, len);
    532         return this;
    533     }
    534
    535     /**
    536      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    537      */
    538     @Override
    539     public synchronized StringBuffer insert(int offset, Object obj) {
    540         toStringCache = null;
    541         super.insert(offset, String.valueOf(obj));
    542         return this;
    543     }
    544
    545     /**
    546      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    547      */
    548     @Override
    549     public synchronized StringBuffer insert(int offset, String str) {
    550         toStringCache = null;
    551         super.insert(offset, str);
    552         return this;
    553     }
    554
    555     /**
    556      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    557      */
    558     @Override
    559     public synchronized StringBuffer insert(int offset, char[] str) {
    560         toStringCache = null;
    561         super.insert(offset, str);
    562         return this;
    563     }
    564
    565     /**
    566      * @throws IndexOutOfBoundsException {@inheritDoc}
    567      * @since      1.5
    568      */
    569     @Override
    570     public StringBuffer insert(int dstOffset, CharSequence s) {
    571         // Note, synchronization achieved via invocations of other StringBuffer methods
    572         // after narrowing of s to specific type
    573         // Ditto for toStringCache clearing
    574         super.insert(dstOffset, s);
    575         return this;
    576     }
    577
    578     /**
    579      * @throws IndexOutOfBoundsException {@inheritDoc}
    580      * @since      1.5
    581      */
    582     @Override
    583     public synchronized StringBuffer insert(int dstOffset, CharSequence s,
    584             int start, int end)
    585     {
    586         toStringCache = null;
    587         super.insert(dstOffset, s, start, end);
    588         return this;
    589     }
    590
    591     /**
    592      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    593      */
    594     @Override
    595     public  StringBuffer insert(int offset, boolean b) {
    596         // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    597         // after conversion of b to String by super class method
    598         // Ditto for toStringCache clearing
    599         super.insert(offset, b);
    600         return this;
    601     }
    602
    603     /**
    604      * @throws IndexOutOfBoundsException {@inheritDoc}
    605      */
    606     @Override
    607     public synchronized StringBuffer insert(int offset, char c) {
    608         toStringCache = null;
    609         super.insert(offset, c);
    610         return this;
    611     }
    612
    613     /**
    614      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    615      */
    616     @Override
    617     public StringBuffer insert(int offset, int i) {
    618         // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    619         // after conversion of i to String by super class method
    620         // Ditto for toStringCache clearing
    621         super.insert(offset, i);
    622         return this;
    623     }
    624
    625     /**
    626      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    627      */
    628     @Override
    629     public StringBuffer insert(int offset, long l) {
    630         // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    631         // after conversion of l to String by super class method
    632         // Ditto for toStringCache clearing
    633         super.insert(offset, l);
    634         return this;
    635     }
    636
    637     /**
    638      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    639      */
    640     @Override
    641     public StringBuffer insert(int offset, float f) {
    642         // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    643         // after conversion of f to String by super class method
    644         // Ditto for toStringCache clearing
    645         super.insert(offset, f);
    646         return this;
    647     }
    648
    649     /**
    650      * @throws StringIndexOutOfBoundsException {@inheritDoc}
    651      */
    652     @Override
    653     public StringBuffer insert(int offset, double d) {
    654         // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
    655         // after conversion of d to String by super class method
    656         // Ditto for toStringCache clearing
    657         super.insert(offset, d);
    658         return this;
    659     }
    660
    661     /**
    662      * @since      1.4
    663      */
    664     @Override
    665     public int indexOf(String str) {
    666         // Note, synchronization achieved via invocations of other StringBuffer methods
    667         return super.indexOf(str);
    668     }
    669
    670     /**
    671      * @since      1.4
    672      */
    673     @Override
    674     public synchronized int indexOf(String str, int fromIndex) {
    675         return super.indexOf(str, fromIndex);
    676     }
    677
    678     /**
    679      * @since      1.4
    680      */
    681     @Override
    682     public int lastIndexOf(String str) {
    683         // Note, synchronization achieved via invocations of other StringBuffer methods
    684         return lastIndexOf(str, count);
    685     }
    686
    687     /**
    688      * @since      1.4
    689      */
    690     @Override
    691     public synchronized int lastIndexOf(String str, int fromIndex) {
    692         return super.lastIndexOf(str, fromIndex);
    693     }
    694
    695     /**
    696      * @since   1.0.2
    697      */
    698     @Override
    699     public synchronized StringBuffer reverse() {
    700         toStringCache = null;
    701         super.reverse();
    702         return this;
    703     }
    704
    705     @Override
    706     @HotSpotIntrinsicCandidate
    707     public synchronized String toString() {
    708         if (toStringCache == null) {
    709             return toStringCache =
    710                     isLatin1() ? StringLatin1.newString(value, 0, count)
    711                                : StringUTF16.newString(value, 0, count);
    712         }
    713         return new String(toStringCache);
    714     }
    715
    716     /**
    717      * Serializable fields for StringBuffer.
    718      *
    719      * @serialField value  char[]
    720      *              The backing character array of this StringBuffer.
    721      * @serialField count int
    722      *              The number of characters in this StringBuffer.
    723      * @serialField shared  boolean
    724      *              A flag indicating whether the backing array is shared.
    725      *              The value is ignored upon deserialization.
    726      */
    727     @java.io.Serial
    728     private static final java.io.ObjectStreamField[] serialPersistentFields =
    729     {
    730         new java.io.ObjectStreamField("value", char[].class),
    731         new java.io.ObjectStreamField("count", Integer.TYPE),
    732         new java.io.ObjectStreamField("shared", Boolean.TYPE),
    733     };
    734
    735     /**
    736      * readObject is called to restore the state of the StringBuffer from
    737      * a stream.

    738      */
    739     @java.io.Serial
    740     private synchronized void writeObject(java.io.ObjectOutputStream s)
    741         throws java.io.IOException {
    742         java.io.ObjectOutputStream.PutField fields = s.putFields();
    743         char[] val = new char[capacity()];
    744         if (isLatin1()) {
    745             StringLatin1.getChars(value, 0, count, val, 0);
    746         } else {
    747             StringUTF16.getChars(value, 0, count, val, 0);
    748         }
    749         fields.put("value", val);
    750         fields.put("count", count);
    751         fields.put("shared", false);
    752         s.writeFields();
    753     }
    754
    755     /**
    756      * readObject is called to restore the state of the StringBuffer from
    757      * a stream.

    758      */
    759     @java.io.Serial
    760     private void readObject(java.io.ObjectInputStream s)
    761         throws java.io.IOException, ClassNotFoundException {
    762         java.io.ObjectInputStream.GetField fields = s.readFields();
    763         char[] val = (char[])fields.get("value", null);
    764         initBytes(val, 0, val.length);
    765         count = fields.get("count", 0);
    766     }
    767
    768     synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
    769         super.getBytes(dst, dstBegin, coder);
    770     }
    771 }
    --- EOF ---