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), //$NON-NLS-1$ 52 new ObjectStreamField("shared", boolean.class), //$NON-NLS-1$ 53 new ObjectStreamField("value", char[].class), }; //$NON-NLS-1$ 54 55 /** 56 * Constructs a new StringBuffer using the default capacity which is 16. 57 */ 58 public StringBuffer() { 59 super(); 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"); //$NON-NLS-1$//$NON-NLS-2$ 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 return append(Double.toString(d)); 141 } 142 143 /** 144 * Adds the string representation of the specified float to the end of this 145 * StringBuffer. 146 * 147 * @param f 148 * the float to append. 149 * @return this StringBuffer. 150 * @see String#valueOf(float) 151 */ 152 public StringBuffer append(float f) { 153 return append(Float.toString(f)); 154 } 155 156 /** 157 * Adds the string representation of the specified integer to the end of 158 * this StringBuffer. 159 * 160 * @param i 161 * the integer to append. 162 * @return this StringBuffer. 163 * @see String#valueOf(int) 164 */ 165 public StringBuffer append(int i) { 166 return append(Integer.toString(i)); 167 } 168 169 /** 170 * Adds the string representation of the specified long to the end of this 171 * StringBuffer. 172 * 173 * @param l 174 * the long to append. 175 * @return this StringBuffer. 176 * @see String#valueOf(long) 177 */ 178 public StringBuffer append(long l) { 179 return append(Long.toString(l)); 180 } 181 182 /** 183 * Adds the string representation of the specified object to the end of this 184 * StringBuffer. 185 * <p> 186 * If the specified object is {@code null} the string {@code "null"} is 187 * appended, otherwise the objects {@code toString} is used to get its 188 * string representation. 189 * 190 * @param obj 191 * the object to append (may be null). 192 * @return this StringBuffer. 193 * @see String#valueOf(Object) 194 */ 195 public synchronized StringBuffer append(Object obj) { 196 if (obj == null) { 197 appendNull(); 198 } else { 199 append0(obj.toString()); 200 } 201 return this; 202 } 203 204 /** 205 * Adds the specified string to the end of this buffer. 206 * <p> 207 * If the specified string is {@code null} the string {@code "null"} is 208 * appended, otherwise the contents of the specified string is appended. 209 * 210 * @param string 211 * the string to append (may be null). 212 * @return this StringBuffer. 213 */ 214 public synchronized StringBuffer append(String string) { 215 append0(string); 216 return this; 217 } 218 219 /** 220 * Adds the specified StringBuffer to the end of this buffer. 221 * <p> 222 * If the specified StringBuffer is {@code null} the string {@code "null"} 223 * is appended, otherwise the contents of the specified StringBuffer is 224 * appended. 225 * 226 * @param sb 227 * the StringBuffer to append (may be null). 228 * @return this StringBuffer. 229 * 230 * @since 1.4 231 */ 232 public synchronized StringBuffer append(StringBuffer sb) { 233 if (sb == null) { 234 appendNull(); 235 } else { 236 synchronized (sb) { 237 append0(sb.getValue(), 0, sb.length()); 238 } 239 } 240 return this; 241 } 242 243 /** 244 * Adds the character array to the end of this buffer. 245 * 246 * @param chars 247 * the character array to append. 248 * @return this StringBuffer. 249 * @throws NullPointerException 250 * if {@code chars} is {@code null}. 251 */ 252 public synchronized StringBuffer append(char chars[]) { 253 append0(chars); 254 return this; 255 } 256 257 /** 258 * Adds the specified sequence of characters to the end of this buffer. 259 * 260 * @param chars 261 * the character array to append. 262 * @param start 263 * the starting offset. 264 * @param length 265 * the number of characters. 266 * @return this StringBuffer. 267 * @throws ArrayIndexOutOfBoundsException 268 * if {@code length < 0} , {@code start < 0} or {@code start + 269 * length > chars.length}. 270 * @throws NullPointerException 271 * if {@code chars} is {@code null}. 272 */ 273 public synchronized StringBuffer append(char chars[], int start, int length) { 274 append0(chars, start, length); 275 return this; 276 } 277 278 /** 279 * Appends the specified CharSequence to this buffer. 280 * <p> 281 * If the specified CharSequence is {@code null} the string {@code "null"} 282 * is appended, otherwise the contents of the specified CharSequence is 283 * appended. 284 * 285 * @param s 286 * the CharSequence to append. 287 * @return this StringBuffer. 288 * @since 1.5 289 */ 290 public synchronized StringBuffer append(CharSequence s) { 291 if (s == null) { 292 appendNull(); 293 } else { 294 append0(s.toString()); 295 } 296 return this; 297 } 298 299 /** 300 * Appends the specified subsequence of the CharSequence to this buffer. 301 * <p> 302 * If the specified CharSequence is {@code null}, then the string {@code 303 * "null"} is used to extract a subsequence. 304 * 305 * @param s 306 * the CharSequence to append. 307 * @param start 308 * the inclusive start index. 309 * @param end 310 * the exclusive end index. 311 * @return this StringBuffer. 312 * @throws IndexOutOfBoundsException 313 * if {@code start} or {@code end} are negative, {@code start} 314 * is greater than {@code end} or {@code end} is greater than 315 * the length of {@code s}. 316 * @since 1.5 317 */ 318 public synchronized StringBuffer append(CharSequence s, int start, int end) { 319 append0(s, start, end); 320 return this; 321 } 322 323 /** 324 * Appends the string representation of the specified Unicode code point to 325 * the end of this buffer. 326 * <p> 327 * The code point is converted to a {@code char[]} as defined by 328 * {@link Character#toChars(int)}. 329 * 330 * @param codePoint 331 * the Unicode code point to encode and append. 332 * @return this StringBuffer. 333 * @see Character#toChars(int) 334 * @since 1.5 335 */ 336 public StringBuffer appendCodePoint(int codePoint) { 337 return append(Character.toChars(codePoint)); 338 } 339 340 @Override 341 public synchronized char charAt(int index) { 342 return super.charAt(index); 343 } 344 345 @Override 346 public synchronized int codePointAt(int index) { 347 return super.codePointAt(index); 348 } 349 350 @Override 351 public synchronized int codePointBefore(int index) { 352 return super.codePointBefore(index); 353 } 354 355 @Override 356 public synchronized int codePointCount(int beginIndex, int endIndex) { 357 return super.codePointCount(beginIndex, endIndex); 358 } 359 360 /** 361 * Deletes a range of characters. 362 * 363 * @param start 364 * the offset of the first character. 365 * @param end 366 * the offset one past the last character. 367 * @return this StringBuffer. 368 * @throws StringIndexOutOfBoundsException 369 * if {@code start < 0}, {@code start > end} or {@code end > 370 * length()}. 371 */ 372 public synchronized StringBuffer delete(int start, int end) { 373 delete0(start, end); 374 return this; 375 } 376 377 /** 378 * Deletes the character at the specified offset. 379 * 380 * @param location 381 * the offset of the character to delete. 382 * @return this StringBuffer. 383 * @throws StringIndexOutOfBoundsException 384 * if {@code location < 0} or {@code location >= length()} 385 */ 386 public synchronized StringBuffer deleteCharAt(int location) { 387 deleteCharAt0(location); 388 return this; 389 } 390 391 @Override 392 public synchronized void ensureCapacity(int min) { 393 super.ensureCapacity(min); 394 } 395 396 /** 397 * Copies the requested sequence of characters to the {@code char[]} passed 398 * starting at {@code idx}. 399 * 400 * @param start 401 * the starting offset of characters to copy. 402 * @param end 403 * the ending offset of characters to copy. 404 * @param buffer 405 * the destination character array. 406 * @param idx 407 * the starting offset in the character array. 408 * @throws IndexOutOfBoundsException 409 * if {@code start < 0}, {@code end > length()}, {@code start > 410 * end}, {@code index < 0}, {@code end - start > buffer.length - 411 * index} 412 */ 413 @Override 414 public synchronized void getChars(int start, int end, char[] buffer, int idx) { 415 super.getChars(start, end, buffer, idx); 416 } 417 418 @Override 419 public synchronized int indexOf(String subString, int start) { 420 return super.indexOf(subString, start); 421 } 422 423 /** 424 * Inserts the character into this buffer at the specified offset. 425 * 426 * @param index 427 * the index at which to insert. 428 * @param ch 429 * the character to insert. 430 * @return this buffer. 431 * @throws ArrayIndexOutOfBoundsException 432 * if {@code index < 0} or {@code index > length()}. 433 */ 434 public synchronized StringBuffer insert(int index, char ch) { 435 insert0(index, ch); 436 return this; 437 } 438 439 /** 440 * Inserts the string representation of the specified boolean into this 441 * buffer at the specified offset. 442 * 443 * @param index 444 * the index at which to insert. 445 * @param b 446 * the boolean to insert. 447 * @return this buffer. 448 * @throws StringIndexOutOfBoundsException 449 * if {@code index < 0} or {@code index > length()}. 450 */ 451 public StringBuffer insert(int index, boolean b) { 452 return insert(index, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ 453 } 454 455 /** 456 * Inserts the string representation of the specified integer into this 457 * buffer at the specified offset. 458 * 459 * @param index 460 * the index at which to insert. 461 * @param i 462 * the integer to insert. 463 * @return this buffer. 464 * @throws StringIndexOutOfBoundsException 465 * if {@code index < 0} or {@code index > length()}. 466 */ 467 public StringBuffer insert(int index, int i) { 468 return insert(index, Integer.toString(i)); 469 } 470 471 /** 472 * Inserts the string representation of the specified long into this buffer 473 * at the specified offset. 474 * 475 * @param index 476 * the index at which to insert. 477 * @param l 478 * the long to insert. 479 * @return this buffer. 480 * @throws StringIndexOutOfBoundsException 481 * if {@code index < 0} or {@code index > length()}. 482 */ 483 public StringBuffer insert(int index, long l) { 484 return insert(index, Long.toString(l)); 485 } 486 487 /** 488 * Inserts the string representation of the specified into this buffer 489 * double at the specified offset. 490 * 491 * @param index 492 * the index at which to insert. 493 * @param d 494 * the double to insert. 495 * @return this buffer. 496 * @throws StringIndexOutOfBoundsException 497 * if {@code index < 0} or {@code index > length()}. 498 */ 499 public StringBuffer insert(int index, double d) { 500 return insert(index, Double.toString(d)); 501 } 502 503 /** 504 * Inserts the string representation of the specified float into this buffer 505 * at the specified offset. 506 * 507 * @param index 508 * the index at which to insert. 509 * @param f 510 * the float to insert. 511 * @return this buffer. 512 * @throws StringIndexOutOfBoundsException 513 * if {@code index < 0} or {@code index > length()}. 514 */ 515 public StringBuffer insert(int index, float f) { 516 return insert(index, Float.toString(f)); 517 } 518 519 /** 520 * Inserts the string representation of the specified object into this 521 * buffer at the specified offset. 522 * <p> 523 * If the specified object is {@code null}, the string {@code "null"} is 524 * inserted, otherwise the objects {@code toString} method is used to get 525 * its string representation. 526 * 527 * @param index 528 * the index at which to insert. 529 * @param obj 530 * the object to insert (may be null). 531 * @return this buffer. 532 * @throws StringIndexOutOfBoundsException 533 * if {@code index < 0} or {@code index > length()}. 534 */ 535 public StringBuffer insert(int index, Object obj) { 536 return insert(index, obj == null ? "null" : obj.toString()); //$NON-NLS-1$ 537 } 538 539 /** 540 * Inserts the string into this buffer at the specified offset. 541 * <p> 542 * If the specified string is {@code null}, the string {@code "null"} is 543 * inserted, otherwise the contents of the string is inserted. 544 * 545 * @param index 546 * the index at which to insert. 547 * @param string 548 * the string to insert (may be null). 549 * @return this buffer. 550 * @throws StringIndexOutOfBoundsException 551 * if {@code index < 0} or {@code index > length()}. 552 */ 553 public synchronized StringBuffer insert(int index, String string) { 554 insert0(index, string); 555 return this; 556 } 557 558 /** 559 * Inserts the character array into this buffer at the specified offset. 560 * 561 * @param index 562 * the index at which to insert. 563 * @param chars 564 * the character array to insert. 565 * @return this buffer. 566 * @throws StringIndexOutOfBoundsException 567 * if {@code index < 0} or {@code index > length()}. 568 * @throws NullPointerException 569 * if {@code chars} is {@code null}. 570 */ 571 public synchronized StringBuffer insert(int index, char[] chars) { 572 insert0(index, chars); 573 return this; 574 } 575 576 /** 577 * Inserts the specified subsequence of characters into this buffer at the 578 * specified index. 579 * 580 * @param index 581 * the index at which to insert. 582 * @param chars 583 * the character array to insert. 584 * @param start 585 * the starting offset. 586 * @param length 587 * the number of characters. 588 * @return this buffer. 589 * @throws NullPointerException 590 * if {@code chars} is {@code null}. 591 * @throws StringIndexOutOfBoundsException 592 * if {@code length < 0}, {@code start < 0}, {@code start + 593 * length > chars.length}, {@code index < 0} or {@code index > 594 * length()} 595 */ 596 public synchronized StringBuffer insert(int index, char chars[], int start, 597 int length) { 598 insert0(index, chars, start, length); 599 return this; 600 } 601 602 /** 603 * Inserts the specified CharSequence into this buffer at the specified 604 * index. 605 * <p> 606 * If the specified CharSequence is {@code null}, the string {@code "null"} 607 * is inserted, otherwise the contents of the CharSequence. 608 * 609 * @param index 610 * The index at which to insert. 611 * @param s 612 * The char sequence to insert. 613 * @return this buffer. 614 * @throws IndexOutOfBoundsException 615 * if {@code index < 0} or {@code index > length()}. 616 * @since 1.5 617 */ 618 public synchronized StringBuffer insert(int index, CharSequence s) { 619 insert0(index, s == null ? "null" : s.toString()); //$NON-NLS-1$ 620 return this; 621 } 622 623 /** 624 * Inserts the specified subsequence into this buffer at the specified 625 * index. 626 * <p> 627 * If the specified CharSequence is {@code null}, the string {@code "null"} 628 * is inserted, otherwise the contents of the CharSequence. 629 * 630 * @param index 631 * The index at which to insert. 632 * @param s 633 * The char sequence to insert. 634 * @param start 635 * The inclusive start index in the char sequence. 636 * @param end 637 * The exclusive end index in the char sequence. 638 * @return this buffer. 639 * @throws IndexOutOfBoundsException 640 * if {@code index} is negative or greater than the current 641 * length, {@code start} or {@code end} are negative, {@code 642 * start} is greater than {@code end} or {@code end} is greater 643 * than the length of {@code s}. 644 * @since 1.5 645 */ 646 public synchronized StringBuffer insert(int index, CharSequence s, 647 int start, int end) { 648 insert0(index, s, start, end); 649 return this; 650 } 651 652 @Override 653 public synchronized int lastIndexOf(String subString, int start) { 654 return super.lastIndexOf(subString, start); 655 } 656 657 @Override 658 public synchronized int offsetByCodePoints(int index, int codePointOffset) { 659 return super.offsetByCodePoints(index, codePointOffset); 660 } 661 662 /** 663 * Replaces the characters in the specified range with the contents of the 664 * specified string. 665 * 666 * @param start 667 * the inclusive begin index. 668 * @param end 669 * the exclusive end index. 670 * @param string 671 * the string that will replace the contents in the range. 672 * @return this buffer. 673 * @throws StringIndexOutOfBoundsException 674 * if {@code start} or {@code end} are negative, {@code start} 675 * is greater than {@code end} or {@code end} is greater than 676 * the length of {@code s}. 677 */ 678 public synchronized StringBuffer replace(int start, int end, String string) { 679 replace0(start, end, string); 680 return this; 681 } 682 683 /** 684 * Reverses the order of characters in this buffer. 685 * 686 * @return this buffer. 687 */ 688 public synchronized StringBuffer reverse() { 689 reverse0(); 690 return this; 691 } 692 693 @Override 694 public synchronized void setCharAt(int index, char ch) { 695 super.setCharAt(index, ch); 696 } 697 698 @Override 699 public synchronized void setLength(int length) { 700 super.setLength(length); 701 } 702 703 @Override 704 public synchronized CharSequence subSequence(int start, int end) { 705 return super.substring(start, end); 706 } 707 708 @Override 709 public synchronized String substring(int start) { 710 return super.substring(start); 711 } 712 713 @Override 714 public synchronized String substring(int start, int end) { 715 return super.substring(start, end); 716 } 717 718 @Override 719 public synchronized String toString() { 720 return super.toString(); 721 } 722 723 @Override 724 public synchronized void trimToSize() { 725 super.trimToSize(); 726 } 727 728 private synchronized void writeObject(ObjectOutputStream out) 729 throws IOException { 730 ObjectOutputStream.PutField fields = out.putFields(); 731 fields.put("count", length()); //$NON-NLS-1$ 732 fields.put("shared", false); //$NON-NLS-1$ 733 fields.put("value", getValue()); //$NON-NLS-1$ 734 out.writeFields(); 735 } 736 737 private void readObject(ObjectInputStream in) throws IOException, 738 ClassNotFoundException { 739 ObjectInputStream.GetField fields = in.readFields(); 740 int count = fields.get("count", 0); //$NON-NLS-1$ 741 char[] value = (char[]) fields.get("value", null); //$NON-NLS-1$ 742 set(value, count); 743 } 744} 745