What do you think about? See attachment. -Ulf
modified checkBounds(byte[] bytes, int offset, int length) to package private checkBounds(int arrayLength, int offset, int count) and added usage from constructors diff --git a/src/share/classes/java/lang/AbstractStringBuilder.java b/src/share/classes/java/lang/AbstractStringBuilder.java --- a/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/share/classes/java/lang/AbstractStringBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,9 @@ * particular sequence of characters, but the length and content of the * sequence can be changed through certain method calls. * - * @author Michael McCloskey - * @since 1.5 + * @author Michael McCloskey + * @author Ulf Zibis, Cologne CoSoCo.de + * @since 1.5 */ abstract class AbstractStringBuilder implements Appendable, CharSequence { /** @@ -63,6 +64,90 @@ } /** + * Common utility method used to bounds check the requested offset & length + * values against the source's length. + * + * @param length length of the source, likely array.length + * @param offset offset to start from + * @param count number of characters to be retrieved + * @throws StringIndexOutOfBoundsException if the bounds would not hold + */ + static void checkBoundsOnCount(int length, int offset, int count) { + int index; + if (offset < 0) + index = offset; + else if (count < 0) + index = offset>length ? offset:count; + // Note: Don't use (offset + length > length), as offset+length + // could overflow if offset or length are near Integer.MAX_VALUE. + else if (offset > length - count) + index = offset>length ? offset : count>length ? count : offset+count; + else + return; + // First calculating the index and then throwing the exception reduces HotSpot + // compiled code of String(int[], int, int) from 8992 to 480 bytes. + throw new StringIndexOutOfBoundsException(index); + } + + /** + * Common utility method used to bounds check the requested begin & end + * values against the source's length. + * + * @param length length of the source, likely array.length + * @param begin begin to start from + * @param end end of characters to be retrieved + * @throws StringIndexOutOfBoundsException if the bounds would not hold + */ + static void checkBoundsOnEnd(int length, int begin, int end) { + int index; + if (begin < 0) + index = begin; + if (end > length) + index = begin>length ? begin:end-begin; + if (end < begin) + index = begin>length ? begin : end<0 ? end : end-begin; + else + return; + throw new StringIndexOutOfBoundsException(index); + } + + /** + * Common utility method used to bounds check the requested index value + * against the source's length. + * + * @param length length of the source, likely array.length + * @param index index to be validated + * @throws StringIndexOutOfBoundsException if the bounds would not hold + */ + static void checkIndexBounds(int length, int index) { + if (index < 0 || index >= length) + throw new StringIndexOutOfBoundsException(index); + } + + /** + * Common utility method used to bounds check the requested begin & end + * values against this string builder's length. + * + * @param begin begin to start from + * @param end end + * @throws StringIndexOutOfBoundsException if the bounds would not hold + */ + void checkBounds(int begin, int end) { + checkBoundsOnEnd(count, begin, end); + } + + /** + * Common utility method used to bounds check the requested index + * value against this string builder's length. + * + * @param index index to start from + * @throws StringIndexOutOfBoundsException if the bounds would not hold + */ + void checkBounds(int index) { + checkIndexBounds(count, index); + } + + /** * Returns the length (character count). * * @return the length of the sequence of characters currently @@ -158,15 +243,11 @@ public void setLength(int newLength) { if (newLength < 0) throw new StringIndexOutOfBoundsException(newLength); - if (newLength > value.length) - expandCapacity(newLength); + ensureCapacity(newLength); - if (count < newLength) { - for (; count < newLength; count++) - value[count] = '\0'; - } else { - count = newLength; - } + if (newLength > count) + Arrays.fill(value, count, newLength, '\0'); + count = newLength; } /** @@ -187,8 +268,7 @@ * negative or greater than or equal to <code>length()</code>. */ public char charAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); + checkBounds(index); return value[index]; } @@ -214,9 +294,7 @@ * sequence. */ public int codePointAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } + checkBounds(index); return Character.codePointAt(value, index); } @@ -242,10 +320,7 @@ * of this sequence. */ public int codePointBefore(int index) { - int i = index - 1; - if ((i < 0) || (i >= count)) { - throw new StringIndexOutOfBoundsException(index); - } + checkBounds(index - 1); return Character.codePointBefore(value, index); } @@ -270,6 +345,7 @@ * <code>beginIndex</code> is larger than <code>endIndex</code>. */ public int codePointCount(int beginIndex, int endIndex) { +// checkBoundsOnCount(beginIndex, endIndex); // would throw StringIndexOutOfBoundsException if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } @@ -296,9 +372,7 @@ * <code>codePointOffset</code> code points. */ public int offsetByCodePoints(int index, int codePointOffset) { - if (index < 0 || index > count) { - throw new IndexOutOfBoundsException(); - } + checkBounds(index); return Character.offsetByCodePointsImpl(value, 0, count, index, codePointOffset); } @@ -333,8 +407,8 @@ * <code>dst.length</code> * </ul> */ - public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) - { + public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { +// checkBoundsOnCount(srcBegin, srcEnd); // would throw sligthly different message if (srcBegin < 0) throw new StringIndexOutOfBoundsException(srcBegin); if ((srcEnd < 0) || (srcEnd > count)) @@ -359,8 +433,7 @@ * negative or greater than or equal to <code>length()</code>. */ public void setCharAt(int index, char ch) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); + checkBounds(index); value[index] = ch; } @@ -465,6 +538,7 @@ public AbstractStringBuilder append(CharSequence s, int start, int end) { if (s == null) s = "null"; +// checkBoundsOnCount(srcBegin, srcEnd); // would throw sligthly different message if ((start < 0) || (end < 0) || (start > end) || (end > s.length())) throw new IndexOutOfBoundsException( "start " + start + ", end " + end + ", s.length() " @@ -697,12 +771,9 @@ * greater than {...@code end}. */ public AbstractStringBuilder delete(int start, int end) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); if (end > count) end = count; - if (start > end) - throw new StringIndexOutOfBoundsException(); + checkBounds(start, end); int len = end - start; if (len > 0) { System.arraycopy(value, start+len, value, start, count-end); @@ -769,8 +840,7 @@ * <code>length()</code>. */ public AbstractStringBuilder deleteCharAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); + checkBounds(index); System.arraycopy(value, index+1, value, index, count-index-1); count--; return this; @@ -796,6 +866,7 @@ * greater than <code>end</code>. */ public AbstractStringBuilder replace(int start, int end, String str) { +// checkBoundsOnCount(start, end); // would throw sligthly different message if (start < 0) throw new StringIndexOutOfBoundsException(start); if (start > count) @@ -876,12 +947,7 @@ * greater than <code>end</code>. */ public String substring(int start, int end) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); - if (end > count) - throw new StringIndexOutOfBoundsException(end); - if (start > end) - throw new StringIndexOutOfBoundsException(end - start); + checkBounds(start, end); return new String(value, start, end - start); } @@ -907,8 +973,8 @@ * {...@code str.length}. */ public AbstractStringBuilder insert(int index, char[] str, int offset, - int len) - { + int len) { +// checkBoundsOnCount(str.length, offset, len); // would throw sligthly different message if ((index < 0) || (index > length())) throw new StringIndexOutOfBoundsException(index); if ((offset < 0) || (len < 0) || (offset > str.length - len)) @@ -979,8 +1045,7 @@ * @throws StringIndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int offset, String str) { - if ((offset < 0) || (offset > length())) - throw new StringIndexOutOfBoundsException(offset); + checkBounds(offset); if (str == null) str = "null"; int len = str.length(); @@ -1018,8 +1083,7 @@ * @throws StringIndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int offset, char[] str) { - if ((offset < 0) || (offset > length())) - throw new StringIndexOutOfBoundsException(offset); + checkBounds(offset); int len = str.length; int newCount = count + len; if (newCount > value.length) diff --git a/src/share/classes/java/lang/Character.java b/src/share/classes/java/lang/Character.java --- a/src/share/classes/java/lang/Character.java +++ b/src/share/classes/java/lang/Character.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,13 @@ */ package java.lang; + import java.util.Map; import java.util.HashMap; import java.util.Locale; +//import static java.lang.AbstractStringBuilder.checkBoundsOnCount; +//import static java.lang.AbstractStringBuilder.checkBoundsOnEnd; +//import static java.lang.AbstractStringBuilder.checkIndexBound; /** * The <code>Character</code> class wraps a value of the primitive @@ -111,13 +115,15 @@ * encoding. For more information on Unicode terminology, refer to the * <a href="http://www.unicode.org/glossary/">Unicode Glossary</a>. * - * @author Lee Boynton - * @author Guy Steele - * @author Akira Tanaka - * @since 1.0 + * @author Lee Boynton + * @author Guy Steele + * @author Akira Tanaka + * @author Ulf Zibis, Cologne CoSoCo.de + * @since 1.0 */ -public final -class Character extends Object implements java.io.Serializable, Comparable<Character> { +public final class Character + implements java.io.Serializable, Comparable<Character> { + /** * The minimum radix available for conversion to and from strings. * The constant value of this field is the smallest value permitted @@ -154,7 +160,7 @@ * * @since 1.0.2 */ - public static final char MIN_VALUE = '\u0000'; + public static final char MIN_VALUE = '\u0000'; /** * The constant value of this field is the largest value of type @@ -162,7 +168,7 @@ * * @since 1.0.2 */ - public static final char MAX_VALUE = '\uFFFF'; + public static final char MAX_VALUE = '\uFFFF'; /** * The <code>Class</code> instance representing the primitive type @@ -393,7 +399,7 @@ /** * Error flag. Use int (code point) to avoid confusion with U+FFFF. */ - static final int ERROR = 0xFFFFFFFF; + static final int ERROR = -1; /** @@ -401,7 +407,7 @@ * values have undefined directionality in the Unicode specification. * @since 1.4 */ - public static final byte DIRECTIONALITY_UNDEFINED = -1; + public static final byte DIRECTIONALITY_UNDEFINED = -1; /** * Strong bidirectional character type "L" in the Unicode specification. @@ -2578,6 +2584,15 @@ } } + /* Common private utility method used to bounds check the requested + * limit value against given index and the source's length. Limit should + * be greater as the index at least by 1. + */ + private static void checkLimitBounds(int length, int index, int limit) { + if (limit <= index || limit > length) + throw new IndexOutOfBoundsException(); + } + /** * Returns a <tt>Character</tt> instance representing the specified * <tt>char</tt> value. @@ -2807,7 +2822,7 @@ * @since 1.5 */ public static int charCount(int codePoint) { - return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT? 2 : 1; + return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1; } /** @@ -2918,12 +2933,11 @@ * @since 1.5 */ public static int codePointAt(char[] a, int index, int limit) { - if (index >= limit || limit < 0 || limit > a.length) { - throw new IndexOutOfBoundsException(); - } + checkLimitBounds(a.length, index, limit); return codePointAtImpl(a, index, limit); } + // throws ArrayIndexOutOfBoundsException static int codePointAtImpl(char[] a, int index, int limit) { char c1 = a[index++]; if (isHighSurrogate(c1)) { @@ -3024,12 +3038,11 @@ * @since 1.5 */ public static int codePointBefore(char[] a, int index, int start) { - if (index <= start || start < 0 || start >= a.length) { - throw new IndexOutOfBoundsException(); - } + checkLimitBounds(0, -index, -start); return codePointBeforeImpl(a, index, start); } + // throws ArrayIndexOutOfBoundsException static int codePointBeforeImpl(char[] a, int index, int start) { char c2 = a[--index]; if (isLowSurrogate(c2)) { @@ -3145,8 +3158,8 @@ * @since 1.5 */ public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) { - int length = seq.length(); - if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) { +// checkBoundsOnEnd(seq.length(), beginIndex, endIndex); // would throw StringIndexOutOfBoundsException + if (beginIndex < 0 || endIndex > seq.length() || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } int n = 0; @@ -3181,12 +3194,14 @@ * @since 1.5 */ public static int codePointCount(char[] a, int offset, int count) { +// checkBoundsOnCount(a.length, offset, count); // would throw StringIndexOutOfBoundsException if (count > a.length - offset || offset < 0 || count < 0) { throw new IndexOutOfBoundsException(); } return codePointCountImpl(a, offset, count); } + // throws ArrayIndexOutOfBoundsException static int codePointCountImpl(char[] a, int offset, int count) { int endIndex = offset + count; int n = 0; @@ -3226,6 +3241,7 @@ public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset) { int length = seq.length(); +// checkIndexBound(length, index); // would throw StringIndexOutOfBoundsException if (index < 0 || index > length) { throw new IndexOutOfBoundsException(); } @@ -3294,6 +3310,7 @@ */ public static int offsetByCodePoints(char[] a, int start, int count, int index, int codePointOffset) { +// checkBoundsOnCount(a.length, start, count); // would throw StringIndexOutOfBoundsException if (count > a.length-start || start < 0 || count < 0 || index < start || index > start+count) { throw new IndexOutOfBoundsException(); @@ -3301,6 +3318,7 @@ return offsetByCodePointsImpl(a, start, count, index, codePointOffset); } + // throws IndexOutOfBoundsException static int offsetByCodePointsImpl(char[]a, int start, int count, int index, int codePointOffset) { int x = index; diff --git a/src/share/classes/java/lang/String.java b/src/share/classes/java/lang/String.java --- a/src/share/classes/java/lang/String.java +++ b/src/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1994-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.lang; -import java.io.ObjectStreamClass; import java.io.ObjectStreamField; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; @@ -37,6 +36,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import static java.lang.AbstractStringBuilder.checkBoundsOnCount; +import static java.lang.AbstractStringBuilder.checkBoundsOnEnd; +import static java.lang.AbstractStringBuilder.checkIndexBounds; /** @@ -99,16 +101,16 @@ * * @author Lee Boynton * @author Arthur van Hoff - * @see java.lang.Object#toString() - * @see java.lang.StringBuffer - * @see java.lang.StringBuilder + * @author Ulf Zibis, Cologne CoSoCo.de + * @see Object#toString() + * @see StringBuffer + * @see StringBuilder * @see java.nio.charset.Charset * @since JDK1.0 */ +public final class String + implements java.io.Serializable, Comparable<String>, CharSequence { -public final class String - implements java.io.Serializable, Comparable<String>, CharSequence -{ /** The value is used for character storage. */ private final char value[]; @@ -137,7 +139,7 @@ * string instance within the stream. */ private static final ObjectStreamField[] serialPersistentFields = - new ObjectStreamField[0]; + new ObjectStreamField[0]; /** * Initializes a newly created {...@code String} object so that it represents @@ -218,16 +220,7 @@ * characters outside the bounds of the {...@code value} array */ public String(char value[], int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > value.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } + checkBoundsOnCount(value.length, offset, count); this.offset = 0; this.count = count; this.value = Arrays.copyOfRange(value, offset, offset+count); @@ -262,16 +255,7 @@ * @since 1.5 */ public String(int[] codePoints, int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > codePoints.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } + checkBoundsOnCount(codePoints.length, offset, count); // Pass 1: Compute precise size of char[] int n = 0; @@ -282,7 +266,8 @@ n += 1; else if (Character.isSupplementaryCodePoint(c)) n += 2; - else throw new IllegalArgumentException(Integer.toString(c)); + else + throw new IllegalArgumentException(Integer.toString(c)); } // Pass 2: Allocate and fill in char[] @@ -343,7 +328,7 @@ */ @Deprecated public String(byte ascii[], int hibyte, int offset, int count) { - checkBounds(ascii, offset, count); + checkBoundsOnCount(ascii.length, offset, count); char value[] = new char[count]; if (hibyte == 0) { @@ -396,19 +381,6 @@ this(ascii, hibyte, 0, ascii.length); } - /* Common private utility method used to bounds check the byte array - * and requested offset & length values used by the String(byte[],..) - * constructors. - */ - private static void checkBounds(byte[] bytes, int offset, int length) { - if (length < 0) - throw new StringIndexOutOfBoundsException(length); - if (offset < 0) - throw new StringIndexOutOfBoundsException(offset); - if (offset > bytes.length - length) - throw new StringIndexOutOfBoundsException(offset + length); - } - /** * Constructs a new {...@code String} by decoding the specified subarray of * bytes using the specified charset. The length of the new {...@code String} @@ -443,11 +415,10 @@ * @since JDK1.1 */ public String(byte bytes[], int offset, int length, String charsetName) - throws UnsupportedEncodingException - { + throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException("charsetName"); - checkBounds(bytes, offset, length); + checkBoundsOnCount(bytes.length, offset, length); char[] v = StringCoding.decode(charsetName, bytes, offset, length); this.offset = 0; this.count = v.length; @@ -487,7 +458,7 @@ public String(byte bytes[], int offset, int length, Charset charset) { if (charset == null) throw new NullPointerException("charset"); - checkBounds(bytes, offset, length); + checkBoundsOnCount(bytes.length, offset, length); char[] v = StringCoding.decode(charset, bytes, offset, length); this.offset = 0; this.count = v.length; @@ -518,8 +489,7 @@ * @since JDK1.1 */ public String(byte bytes[], String charsetName) - throws UnsupportedEncodingException - { + throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); } @@ -574,7 +544,7 @@ * @since JDK1.1 */ public String(byte bytes[], int offset, int length) { - checkBounds(bytes, offset, length); + checkBoundsOnCount(bytes.length, offset, length); char[] v = StringCoding.decode(bytes, offset, length); this.offset = 0; this.count = v.length; @@ -647,6 +617,20 @@ this.count = count; } + /* Common private utility method used to bounds check the requested + * begin & end values against this string's length. + */ + private void checkBounds(int begin, int end) { + checkBoundsOnEnd(count, begin, end); + } + + /* Common private utility method used to bounds check the requested + * index value against this string's length. + */ + private void checkBounds(int index) { + checkIndexBounds(count, index); + } + /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode @@ -690,9 +674,7 @@ * string. */ public char charAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } + checkBounds(index); return value[index + offset]; } @@ -719,9 +701,7 @@ * @since 1.5 */ public int codePointAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } + checkBounds(index); return Character.codePointAtImpl(value, offset + index, offset + count); } @@ -748,10 +728,7 @@ * @since 1.5 */ public int codePointBefore(int index) { - int i = index - 1; - if ((i < 0) || (i >= count)) { - throw new StringIndexOutOfBoundsException(index); - } + checkBounds(index - 1); return Character.codePointBeforeImpl(value, offset + index, offset); } @@ -777,9 +754,7 @@ * @since 1.5 */ public int codePointCount(int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { - throw new IndexOutOfBoundsException(); - } + checkBounds(beginIndex, endIndex); return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); } @@ -804,16 +779,19 @@ * @since 1.5 */ public int offsetByCodePoints(int index, int codePointOffset) { - if (index < 0 || index > count) { - throw new IndexOutOfBoundsException(); - } + checkBounds(index); return Character.offsetByCodePointsImpl(value, offset, count, offset+index, codePointOffset) - offset; } /** - * Copy characters from this string into dst starting at dstBegin. - * This method doesn't perform any range checking. + * Copies characters from this string into dst[] starting at dstBegin. + * This method doesn't perform any range checking. Is used in this package + * by AbstractStringBuilder. + * + * @param dst the destination array + * @param dstBegin the start offset in the destination array + * @throws IndexOutOfBoundsException if any of the bounds do not hold */ void getChars(char dst[], int dstBegin) { System.arraycopy(value, offset, dst, dstBegin, count); @@ -850,15 +828,7 @@ * <code>dst.length</code></ul> */ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > count) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } + checkBounds(srcBegin, srcEnd); System.arraycopy(value, offset + srcBegin, dst, dstBegin, srcEnd - srcBegin); } @@ -908,15 +878,7 @@ */ @Deprecated public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > count) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } + checkBounds(srcBegin, srcEnd); int j = dstBegin; int n = offset + srcEnd; int i = offset + srcBegin; @@ -1939,15 +1901,7 @@ * <code>endIndex</code>. */ public String substring(int beginIndex, int endIndex) { - if (beginIndex < 0) { - throw new StringIndexOutOfBoundsException(beginIndex); - } - if (endIndex > count) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (beginIndex > endIndex) { - throw new StringIndexOutOfBoundsException(endIndex - beginIndex); - } + checkBounds(beginIndex, endIndex); return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value); } @@ -1981,7 +1935,7 @@ * @spec JSR-51 */ public CharSequence subSequence(int beginIndex, int endIndex) { - return this.substring(beginIndex, endIndex); + return substring(beginIndex, endIndex); } /**