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