1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.lang; 19 20import java.io.IOException; 21import java.io.ObjectInputStream; 22import java.io.ObjectOutputStream; 23import java.io.ObjectStreamField; 24import java.io.Serializable; 25 26/** 27 * A modifiable {@link CharSequence sequence of characters} for use in creating 28 * strings, where all accesses are synchronized. This class has mostly been replaced 29 * by {@link StringBuilder} because this synchronization is rarely useful. This 30 * class is mainly used to interact with legacy APIs that expose it. 31 * 32 * <p>For particularly complex string-building needs, consider {@link java.util.Formatter}. 33 * 34 * <p>The majority of the modification methods on this class return {@code 35 * this} so that method calls can be chained together. For example: 36 * {@code new StringBuffer("a").append("b").append("c").toString()}. 37 * 38 * @see CharSequence 39 * @see Appendable 40 * @see StringBuilder 41 * @see String 42 * @see String#format 43 * @since 1.0 44 */ 45public final class StringBuffer extends AbstractStringBuilder implements 46 Appendable, Serializable, CharSequence { 47 48 private static final long serialVersionUID = 3388685877147921107L; 49 50 private static final ObjectStreamField[] serialPersistentFields = { 51 new ObjectStreamField("count", int.class), 52 new ObjectStreamField("shared", boolean.class), 53 new ObjectStreamField("value", char[].class), 54 }; 55 56 /** 57 * Constructs a new StringBuffer using the default capacity which is 16. 58 */ 59 public StringBuffer() { 60 } 61 62 /** 63 * Constructs a new StringBuffer using the specified capacity. 64 * 65 * @param capacity 66 * the initial capacity. 67 */ 68 public StringBuffer(int capacity) { 69 super(capacity); 70 } 71 72 /** 73 * Constructs a new StringBuffer containing the characters in the specified 74 * string. The capacity of the new buffer will be the length of the 75 * {@code String} plus the default capacity. 76 * 77 * @param string 78 * the string content with which to initialize the new instance. 79 * @throws NullPointerException 80 * if {@code string} is {@code null}. 81 */ 82 public StringBuffer(String string) { 83 super(string); 84 } 85 86 /** 87 * Constructs a StringBuffer and initializes it with the content from the 88 * specified {@code CharSequence}. The capacity of the new buffer will be 89 * the length of the {@code CharSequence} plus the default capacity. 90 * 91 * @param cs 92 * the content to initialize the instance. 93 * @throws NullPointerException 94 * if {@code cs} is {@code null}. 95 * @since 1.5 96 */ 97 public StringBuffer(CharSequence cs) { 98 super(cs.toString()); 99 } 100 101 /** 102 * Adds the string representation of the specified boolean to the end of 103 * this StringBuffer. 104 * <p> 105 * If the argument is {@code true} the string {@code "true"} is appended, 106 * otherwise the string {@code "false"} is appended. 107 * 108 * @param b 109 * the boolean to append. 110 * @return this StringBuffer. 111 * @see String#valueOf(boolean) 112 */ 113 public StringBuffer append(boolean b) { 114 return append(b ? "true" : "false"); 115 } 116 117 /** 118 * Adds the specified character to the end of this buffer. 119 * 120 * @param ch 121 * the character to append. 122 * @return this StringBuffer. 123 * @see String#valueOf(char) 124 */ 125 public synchronized StringBuffer append(char ch) { 126 append0(ch); 127 return this; 128 } 129 130 /** 131 * Adds the string representation of the specified double to the end of this 132 * StringBuffer. 133 * 134 * @param d 135 * the double to append. 136 * @return this StringBuffer. 137 * @see String#valueOf(double) 138 */ 139 public StringBuffer append(double d) { 140 RealToString.getInstance().appendDouble(this, d); 141 return this; 142 } 143 144 /** 145 * Adds the string representation of the specified float to the end of this 146 * StringBuffer. 147 * 148 * @param f 149 * the float to append. 150 * @return this StringBuffer. 151 * @see String#valueOf(float) 152 */ 153 public StringBuffer append(float f) { 154 RealToString.getInstance().appendFloat(this, f); 155 return this; 156 } 157 158 /** 159 * Adds the string representation of the specified integer to the end of 160 * this StringBuffer. 161 * 162 * @param i 163 * the integer to append. 164 * @return this StringBuffer. 165 * @see String#valueOf(int) 166 */ 167 public StringBuffer append(int i) { 168 IntegralToString.appendInt(this, i); 169 return this; 170 } 171 172 /** 173 * Adds the string representation of the specified long to the end of this 174 * StringBuffer. 175 * 176 * @param l 177 * the long to append. 178 * @return this StringBuffer. 179 * @see String#valueOf(long) 180 */ 181 public StringBuffer append(long l) { 182 IntegralToString.appendLong(this, l); 183 return this; 184 } 185 186 /** 187 * Adds the string representation of the specified object to the end of this 188 * StringBuffer. 189 * <p> 190 * If the specified object is {@code null} the string {@code "null"} is 191 * appended, otherwise the objects {@code toString} is used to get its 192 * string representation. 193 * 194 * @param obj 195 * the object to append (may be null). 196 * @return this StringBuffer. 197 * @see String#valueOf(Object) 198 */ 199 public synchronized StringBuffer append(Object obj) { 200 if (obj == null) { 201 appendNull(); 202 } else { 203 append0(obj.toString()); 204 } 205 return this; 206 } 207 208 /** 209 * Adds the specified string to the end of this buffer. 210 * <p> 211 * If the specified string is {@code null} the string {@code "null"} is 212 * appended, otherwise the contents of the specified string is appended. 213 * 214 * @param string 215 * the string to append (may be null). 216 * @return this StringBuffer. 217 */ 218 public synchronized StringBuffer append(String string) { 219 append0(string); 220 return this; 221 } 222 223 /** 224 * Adds the specified StringBuffer to the end of this buffer. 225 * <p> 226 * If the specified StringBuffer is {@code null} the string {@code "null"} 227 * is appended, otherwise the contents of the specified StringBuffer is 228 * appended. 229 * 230 * @param sb 231 * the StringBuffer to append (may be null). 232 * @return this StringBuffer. 233 * 234 * @since 1.4 235 */ 236 public synchronized StringBuffer append(StringBuffer sb) { 237 if (sb == null) { 238 appendNull(); 239 } else { 240 synchronized (sb) { 241 append0(sb.getValue(), 0, sb.length()); 242 } 243 } 244 return this; 245 } 246 247 /** 248 * Adds the character array to the end of this buffer. 249 * 250 * @param chars 251 * the character array to append. 252 * @return this StringBuffer. 253 * @throws NullPointerException 254 * if {@code chars} is {@code null}. 255 */ 256 public synchronized StringBuffer append(char[] chars) { 257 append0(chars); 258 return this; 259 } 260 261 /** 262 * Adds the specified sequence of characters to the end of this buffer. 263 * 264 * @param chars 265 * the character array to append. 266 * @param start 267 * the starting offset. 268 * @param length 269 * the number of characters. 270 * @return this StringBuffer. 271 * @throws ArrayIndexOutOfBoundsException 272 * if {@code length < 0} , {@code start < 0} or {@code start + 273 * length > chars.length}. 274 * @throws NullPointerException 275 * if {@code chars} is {@code null}. 276 */ 277 public synchronized StringBuffer append(char[] chars, int start, int length) { 278 append0(chars, start, length); 279 return this; 280 } 281 282 /** 283 * Appends the specified CharSequence to this buffer. 284 * <p> 285 * If the specified CharSequence is {@code null} the string {@code "null"} 286 * is appended, otherwise the contents of the specified CharSequence is 287 * appended. 288 * 289 * @param s 290 * the CharSequence to append. 291 * @return this StringBuffer. 292 * @since 1.5 293 */ 294 public synchronized StringBuffer append(CharSequence s) { 295 if (s == null) { 296 appendNull(); 297 } else { 298 append0(s, 0, s.length()); 299 } 300 return this; 301 } 302 303 /** 304 * Appends the specified subsequence of the CharSequence to this buffer. 305 * <p> 306 * If the specified CharSequence is {@code null}, then the string {@code 307 * "null"} is used to extract a subsequence. 308 * 309 * @param s 310 * the CharSequence to append. 311 * @param start 312 * the inclusive start index. 313 * @param end 314 * the exclusive end index. 315 * @return this StringBuffer. 316 * @throws IndexOutOfBoundsException 317 * if {@code start} or {@code end} are negative, {@code start} 318 * is greater than {@code end} or {@code end} is greater than 319 * the length of {@code s}. 320 * @since 1.5 321 */ 322 public synchronized StringBuffer append(CharSequence s, int start, int end) { 323 append0(s, start, end); 324 return this; 325 } 326 327 /** 328 * Appends the string representation of the specified Unicode code point to 329 * the end of this buffer. 330 * <p> 331 * The code point is converted to a {@code char[]} as defined by 332 * {@link Character#toChars(int)}. 333 * 334 * @param codePoint 335 * the Unicode code point to encode and append. 336 * @return this StringBuffer. 337 * @see Character#toChars(int) 338 * @since 1.5 339 */ 340 public StringBuffer appendCodePoint(int codePoint) { 341 return append(Character.toChars(codePoint)); 342 } 343 344 @Override 345 public synchronized char charAt(int index) { 346 return super.charAt(index); 347 } 348 349 @Override 350 public synchronized int codePointAt(int index) { 351 return super.codePointAt(index); 352 } 353 354 @Override 355 public synchronized int codePointBefore(int index) { 356 return super.codePointBefore(index); 357 } 358 359 @Override 360 public synchronized int codePointCount(int beginIndex, int endIndex) { 361 return super.codePointCount(beginIndex, endIndex); 362 } 363 364 /** 365 * Deletes a range of characters. 366 * 367 * @param start 368 * the offset of the first character. 369 * @param end 370 * the offset one past the last character. 371 * @return this StringBuffer. 372 * @throws StringIndexOutOfBoundsException 373 * if {@code start < 0}, {@code start > end} or {@code end > 374 * length()}. 375 */ 376 public synchronized StringBuffer delete(int start, int end) { 377 delete0(start, end); 378 return this; 379 } 380 381 /** 382 * Deletes the character at the specified offset. 383 * 384 * @param location 385 * the offset of the character to delete. 386 * @return this StringBuffer. 387 * @throws StringIndexOutOfBoundsException 388 * if {@code location < 0} or {@code location >= length()} 389 */ 390 public synchronized StringBuffer deleteCharAt(int location) { 391 deleteCharAt0(location); 392 return this; 393 } 394 395 @Override 396 public synchronized void ensureCapacity(int min) { 397 super.ensureCapacity(min); 398 } 399 400 /** 401 * Copies the requested sequence of characters to the {@code char[]} passed 402 * starting at {@code idx}. 403 * 404 * @param start 405 * the starting offset of characters to copy. 406 * @param end 407 * the ending offset of characters to copy. 408 * @param buffer 409 * the destination character array. 410 * @param idx 411 * the starting offset in the character array. 412 * @throws IndexOutOfBoundsException 413 * if {@code start < 0}, {@code end > length()}, {@code start > 414 * end}, {@code index < 0}, {@code end - start > buffer.length - 415 * index} 416 */ 417 @Override 418 public synchronized void getChars(int start, int end, char[] buffer, int idx) { 419 super.getChars(start, end, buffer, idx); 420 } 421 422 @Override 423 public synchronized int indexOf(String subString, int start) { 424 return super.indexOf(subString, start); 425 } 426 427 /** 428 * Inserts the character into this buffer at the specified offset. 429 * 430 * @param index 431 * the index at which to insert. 432 * @param ch 433 * the character to insert. 434 * @return this buffer. 435 * @throws ArrayIndexOutOfBoundsException 436 * if {@code index < 0} or {@code index > length()}. 437 */ 438 public synchronized StringBuffer insert(int index, char ch) { 439 insert0(index, ch); 440 return this; 441 } 442 443 /** 444 * Inserts the string representation of the specified boolean into this 445 * buffer at the specified offset. 446 * 447 * @param index 448 * the index at which to insert. 449 * @param b 450 * the boolean to insert. 451 * @return this buffer. 452 * @throws StringIndexOutOfBoundsException 453 * if {@code index < 0} or {@code index > length()}. 454 */ 455 public StringBuffer insert(int index, boolean b) { 456 return insert(index, b ? "true" : "false"); 457 } 458 459 /** 460 * Inserts the string representation of the specified integer into this 461 * buffer at the specified offset. 462 * 463 * @param index 464 * the index at which to insert. 465 * @param i 466 * the integer to insert. 467 * @return this buffer. 468 * @throws StringIndexOutOfBoundsException 469 * if {@code index < 0} or {@code index > length()}. 470 */ 471 public StringBuffer insert(int index, int i) { 472 return insert(index, Integer.toString(i)); 473 } 474 475 /** 476 * Inserts the string representation of the specified long into this buffer 477 * at the specified offset. 478 * 479 * @param index 480 * the index at which to insert. 481 * @param l 482 * the long to insert. 483 * @return this buffer. 484 * @throws StringIndexOutOfBoundsException 485 * if {@code index < 0} or {@code index > length()}. 486 */ 487 public StringBuffer insert(int index, long l) { 488 return insert(index, Long.toString(l)); 489 } 490 491 /** 492 * Inserts the string representation of the specified into this buffer 493 * double at the specified offset. 494 * 495 * @param index 496 * the index at which to insert. 497 * @param d 498 * the double to insert. 499 * @return this buffer. 500 * @throws StringIndexOutOfBoundsException 501 * if {@code index < 0} or {@code index > length()}. 502 */ 503 public StringBuffer insert(int index, double d) { 504 return insert(index, Double.toString(d)); 505 } 506 507 /** 508 * Inserts the string representation of the specified float into this buffer 509 * at the specified offset. 510 * 511 * @param index 512 * the index at which to insert. 513 * @param f 514 * the float to insert. 515 * @return this buffer. 516 * @throws StringIndexOutOfBoundsException 517 * if {@code index < 0} or {@code index > length()}. 518 */ 519 public StringBuffer insert(int index, float f) { 520 return insert(index, Float.toString(f)); 521 } 522 523 /** 524 * Inserts the string representation of the specified object into this 525 * buffer at the specified offset. 526 * <p> 527 * If the specified object is {@code null}, the string {@code "null"} is 528 * inserted, otherwise the objects {@code toString} method is used to get 529 * its string representation. 530 * 531 * @param index 532 * the index at which to insert. 533 * @param obj 534 * the object to insert (may be null). 535 * @return this buffer. 536 * @throws StringIndexOutOfBoundsException 537 * if {@code index < 0} or {@code index > length()}. 538 */ 539 public StringBuffer insert(int index, Object obj) { 540 return insert(index, obj == null ? "null" : obj.toString()); 541 } 542 543 /** 544 * Inserts the string into this buffer at the specified offset. 545 * <p> 546 * If the specified string is {@code null}, the string {@code "null"} is 547 * inserted, otherwise the contents of the string is inserted. 548 * 549 * @param index 550 * the index at which to insert. 551 * @param string 552 * the string to insert (may be null). 553 * @return this buffer. 554 * @throws StringIndexOutOfBoundsException 555 * if {@code index < 0} or {@code index > length()}. 556 */ 557 public synchronized StringBuffer insert(int index, String string) { 558 insert0(index, string); 559 return this; 560 } 561 562 /** 563 * Inserts the character array into this buffer at the specified offset. 564 * 565 * @param index 566 * the index at which to insert. 567 * @param chars 568 * the character array to insert. 569 * @return this buffer. 570 * @throws StringIndexOutOfBoundsException 571 * if {@code index < 0} or {@code index > length()}. 572 * @throws NullPointerException 573 * if {@code chars} is {@code null}. 574 */ 575 public synchronized StringBuffer insert(int index, char[] chars) { 576 insert0(index, chars); 577 return this; 578 } 579 580 /** 581 * Inserts the specified subsequence of characters into this buffer at the 582 * specified index. 583 * 584 * @param index 585 * the index at which to insert. 586 * @param chars 587 * the character array to insert. 588 * @param start 589 * the starting offset. 590 * @param length 591 * the number of characters. 592 * @return this buffer. 593 * @throws NullPointerException 594 * if {@code chars} is {@code null}. 595 * @throws StringIndexOutOfBoundsException 596 * if {@code length < 0}, {@code start < 0}, {@code start + 597 * length > chars.length}, {@code index < 0} or {@code index > 598 * length()} 599 */ 600 public synchronized StringBuffer insert(int index, char[] chars, int start, int length) { 601 insert0(index, chars, start, length); 602 return this; 603 } 604 605 /** 606 * Inserts the specified CharSequence into this buffer at the specified 607 * index. 608 * <p> 609 * If the specified CharSequence is {@code null}, the string {@code "null"} 610 * is inserted, otherwise the contents of the CharSequence. 611 * 612 * @param index 613 * The index at which to insert. 614 * @param s 615 * The char sequence to insert. 616 * @return this buffer. 617 * @throws IndexOutOfBoundsException 618 * if {@code index < 0} or {@code index > length()}. 619 * @since 1.5 620 */ 621 public synchronized StringBuffer insert(int index, CharSequence s) { 622 insert0(index, s == null ? "null" : s.toString()); 623 return this; 624 } 625 626 /** 627 * Inserts the specified subsequence into this buffer at the specified 628 * index. 629 * <p> 630 * If the specified CharSequence is {@code null}, the string {@code "null"} 631 * is inserted, otherwise the contents of the CharSequence. 632 * 633 * @param index 634 * The index at which to insert. 635 * @param s 636 * The char sequence to insert. 637 * @param start 638 * The inclusive start index in the char sequence. 639 * @param end 640 * The exclusive end index in the char sequence. 641 * @return this buffer. 642 * @throws IndexOutOfBoundsException 643 * if {@code index} is negative or greater than the current 644 * length, {@code start} or {@code end} are negative, {@code 645 * start} is greater than {@code end} or {@code end} is greater 646 * than the length of {@code s}. 647 * @since 1.5 648 */ 649 public synchronized StringBuffer insert(int index, CharSequence s, 650 int start, int end) { 651 insert0(index, s, start, end); 652 return this; 653 } 654 655 @Override 656 public synchronized int lastIndexOf(String subString, int start) { 657 return super.lastIndexOf(subString, start); 658 } 659 660 @Override 661 public synchronized int offsetByCodePoints(int index, int codePointOffset) { 662 return super.offsetByCodePoints(index, codePointOffset); 663 } 664 665 /** 666 * Replaces the characters in the specified range with the contents of the 667 * specified string. 668 * 669 * @param start 670 * the inclusive begin index. 671 * @param end 672 * the exclusive end index. 673 * @param string 674 * the string that will replace the contents in the range. 675 * @return this buffer. 676 * @throws StringIndexOutOfBoundsException 677 * if {@code start} or {@code end} are negative, {@code start} 678 * is greater than {@code end} or {@code end} is greater than 679 * the length of {@code s}. 680 */ 681 public synchronized StringBuffer replace(int start, int end, String string) { 682 replace0(start, end, string); 683 return this; 684 } 685 686 /** 687 * Reverses the order of characters in this buffer. 688 * 689 * @return this buffer. 690 */ 691 public synchronized StringBuffer reverse() { 692 reverse0(); 693 return this; 694 } 695 696 @Override 697 public synchronized void setCharAt(int index, char ch) { 698 super.setCharAt(index, ch); 699 } 700 701 @Override 702 public synchronized void setLength(int length) { 703 super.setLength(length); 704 } 705 706 @Override 707 public synchronized CharSequence subSequence(int start, int end) { 708 return super.substring(start, end); 709 } 710 711 @Override 712 public synchronized String substring(int start) { 713 return super.substring(start); 714 } 715 716 @Override 717 public synchronized String substring(int start, int end) { 718 return super.substring(start, end); 719 } 720 721 @Override 722 public synchronized String toString() { 723 return super.toString(); 724 } 725 726 @Override 727 public synchronized void trimToSize() { 728 super.trimToSize(); 729 } 730 731 private synchronized void writeObject(ObjectOutputStream out) 732 throws IOException { 733 ObjectOutputStream.PutField fields = out.putFields(); 734 fields.put("count", length()); 735 fields.put("shared", false); 736 fields.put("value", getValue()); 737 out.writeFields(); 738 } 739 740 private void readObject(ObjectInputStream in) throws IOException, 741 ClassNotFoundException { 742 ObjectInputStream.GetField fields = in.readFields(); 743 int count = fields.get("count", 0); 744 char[] value = (char[]) fields.get("value", null); 745 set(value, count); 746 } 747} 748