RFR 8135248: Add utility methods to check indexes and ranges
Paul Sandoz
paul.sandoz at oracle.com
Mon Sep 21 15:21:04 UTC 2015
On 21 Sep 2015, at 16:17, Roger Riggs <Roger.Riggs at oracle.com> wrote:
> Hi Paul,
>
> java.util.Arrays.java: line 5236: new IndexOutOfBoundsException()
> - It is always appreciated when debugging to be given a message with the index that is out of range and the range expected.
>
Added:
? new IndexOutOfBoundsException(String.format(
"Out of bounds for range [0, %d) with out of bound values %d and %d", length, a, b))
> When converting existing code, is it expected that the exception messages will be unchanged?
>
Yes, that is intention, based on looking at various use-cases in Arrays/Spliterators/String/AbstractString/AbstractStringBuilder/*Buffer. I could have missed a few cases. Note that one can always play the “capture” card at the expense of an allocation per check. which may be less of a concern for the sub-range checks.
> I can't quite visualize how this would be applied to existing code.
Existing code would provide an instance of OutOfBoundsToException for each particular use-case.
Take this following method in String:
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
Which could be updated as follows (modulo using lambdas early in at start up):
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
Arrays.checkFromToIndex(srcBegin, srcEnd, value.length, (f, t, l) -> {
long v;
if (f < 0) {
v = f;
} else if (t > l) {
v = t;
} else v = t - f;
return new StringIndexOutOfBoundsException((int) v);
});
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
Or the following in AbstractStringBuilder:
public AbstractStringBuilder insert(int index, char[] str, int offset,
int len)
{
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len);
System.arraycopy(value, index, value, index + len, count - index);
System.arraycopy(str, offset, value, index, len);
count += len;
return this;
}
public AbstractStringBuilder insert(int index, char[] str, int offset,
int len)
{
Arrays.checkIndex(index, length(),
(i, a, l) -> new StringIndexOutOfBoundsException((int) i));
Arrays.checkFromIndexSize(offset, len, str.length,
(f, s, l) -> new StringIndexOutOfBoundsException(
"offset " + f + ", len " + s + ", str.length " + l));
ensureCapacityInternal(count + len);
System.arraycopy(value, index, value, index + len, count - index);
System.arraycopy(str, offset, value, index, len);
count += len;
return this;
}
The casts obviously suck, but that could be solved with a new (package private, maybe) constructor. One thing we could do to improve the situation is add factory methods to IOOBE, AIOOBE, SIOOBE for the three use-cases such that method refs could be easily be used.
> Will there be any benefit to adding static checking methods to the typically thrown exceptions
> that can be used as method references instead of the implicitly defined lambdas?
>
> typo:
>
> test/java/util/Arrays/CheckIndex.java:
> - line 78, 91, etc "withing" -> “within”
>
Thanks, updated,
Paul.
More information about the core-libs-dev
mailing list