< prev index next >

src/java.base/share/classes/java/util/Objects.java

Print this page
rev 14354 : 8155794: Move Objects.checkIndex BiFunction accepting methods to an internal package
Reviewed-by:

*** 1,7 **** /* ! * Copyright (c) 2009, 2015, Oracle and/or its affiliates. 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2009, 2016, Oracle and/or its affiliates. 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,36 **** * questions. */ package java.util; ! import jdk.internal.HotSpotIntrinsicCandidate; - import java.util.function.BiFunction; - import java.util.function.Function; import java.util.function.Supplier; /** * This class consists of {@code static} utility methods for operating * on objects, or checking certain conditions before operation. These utilities --- 23,35 ---- * questions. */ package java.util; ! import jdk.internal.util.Preconditions; ! import jdk.internal.vm.annotation.ForceInline; import java.util.function.Supplier; /** * This class consists of {@code static} utility methods for operating * on objects, or checking certain conditions before operation. These utilities
*** 347,522 **** throw new NullPointerException(messageSupplier.get()); return obj; } /** - * Maps out-of-bounds values to a runtime exception. - * - * @param checkKind the kind of bounds check, whose name may correspond - * to the name of one of the range check methods, checkIndex, - * checkFromToIndex, checkFromIndexSize - * @param args the out-of-bounds arguments that failed the range check. - * If the checkKind corresponds a the name of a range check method - * then the bounds arguments are those that can be passed in order - * to the method. - * @param oobef the exception formatter that when applied with a checkKind - * and a list out-of-bounds arguments returns a runtime exception. - * If {@code null} then, it is as if an exception formatter was - * supplied that returns {@link IndexOutOfBoundsException} for any - * given arguments. - * @return the runtime exception - */ - private static RuntimeException outOfBounds( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobef, - String checkKind, - Integer... args) { - List<Integer> largs = List.of(args); - RuntimeException e = oobef == null - ? null : oobef.apply(checkKind, largs); - return e == null - ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; - } - - // Specific out-of-bounds exception producing methods that avoid - // the varargs-based code in the critical methods there by reducing their - // the byte code size, and therefore less likely to peturb inlining - - private static RuntimeException outOfBoundsCheckIndex( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int index, int length) { - return outOfBounds(oobe, "checkIndex", index, length); - } - - private static RuntimeException outOfBoundsCheckFromToIndex( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int fromIndex, int toIndex, int length) { - return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); - } - - private static RuntimeException outOfBoundsCheckFromIndexSize( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int fromIndex, int size, int length) { - return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); - } - - /** - * Returns an out-of-bounds exception formatter from an given exception - * factory. The exception formatter is a function that formats an - * out-of-bounds message from its arguments and applies that message to the - * given exception factory to produce and relay an exception. - * - * <p>The exception formatter accepts two arguments: a {@code String} - * describing the out-of-bounds range check that failed, referred to as the - * <em>check kind</em>; and a {@code List<Integer>} containing the - * out-of-bound integer values that failed the check. The list of - * out-of-bound values is not modified. - * - * <p>Three check kinds are supported {@code checkIndex}, - * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding - * respectively to the specified application of an exception formatter as an - * argument to the out-of-bounds range check methods - * {@link #checkIndex(int, int, BiFunction) checkIndex}, - * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and - * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. - * Thus a supported check kind corresponds to a method name and the - * out-of-bound integer values correspond to method argument values, in - * order, preceding the exception formatter argument (similar in many - * respects to the form of arguments required for a reflective invocation of - * such a range check method). - * - * <p>Formatter arguments conforming to such supported check kinds will - * produce specific exception messages describing failed out-of-bounds - * checks. Otherwise, more generic exception messages will be produced in - * any of the following cases: the check kind is supported but fewer - * or more out-of-bounds values are supplied, the check kind is not - * supported, the check kind is {@code null}, or the list of out-of-bound - * values is {@code null}. - * - * @apiNote - * This method produces an out-of-bounds exception formatter that can be - * passed as an argument to any of the supported out-of-bounds range check - * methods declared by {@code Objects}. For example, a formatter producing - * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a - * {@code static final} field as follows: - * <pre>{@code - * static final - * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF = - * outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new); - * }</pre> - * The formatter instance {@code AIOOBEF} may be passed as an argument to an - * out-of-bounds range check method, such as checking if an {@code index} - * is within the bounds of a {@code limit}: - * <pre>{@code - * checkIndex(index, limit, AIOOBEF); - * }</pre> - * If the bounds check fails then the range check method will throw an - * {@code ArrayIndexOutOfBoundsException} with an appropriate exception - * message that is a produced from {@code AIOOBEF} as follows: - * <pre>{@code - * AIOOBEF.apply("checkIndex", List.of(index, limit)); - * }</pre> - * - * @param f the exception factory, that produces an exception from a message - * where the message is produced and formatted by the returned - * exception formatter. If this factory is stateless and side-effect - * free then so is the returned formatter. - * Exceptions thrown by the factory are relayed to the caller - * of the returned formatter. - * @param <X> the type of runtime exception to be returned by the given - * exception factory and relayed by the exception formatter - * @return the out-of-bounds exception formatter - */ - public static <X extends RuntimeException> - BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) { - // Use anonymous class to avoid bootstrap issues if this method is - // used early in startup - return new BiFunction<String, List<Integer>, X>() { - @Override - public X apply(String checkKind, List<Integer> args) { - return f.apply(outOfBoundsMessage(checkKind, args)); - } - }; - } - - private static String outOfBoundsMessage(String checkKind, List<Integer> args) { - if (checkKind == null && args == null) { - return String.format("Range check failed"); - } else if (checkKind == null) { - return String.format("Range check failed: %s", args); - } else if (args == null) { - return String.format("Range check failed: %s", checkKind); - } - - int argSize = 0; - switch (checkKind) { - case "checkIndex": - argSize = 2; - break; - case "checkFromToIndex": - case "checkFromIndexSize": - argSize = 3; - break; - default: - } - - // Switch to default if fewer or more arguments than required are supplied - switch ((args.size() != argSize) ? "" : checkKind) { - case "checkIndex": - return String.format("Index %d out-of-bounds for length %d", - args.get(0), args.get(1)); - case "checkFromToIndex": - return String.format("Range [%d, %d) out-of-bounds for length %d", - args.get(0), args.get(1), args.get(2)); - case "checkFromIndexSize": - return String.format("Range [%d, %<d + %d) out-of-bounds for length %d", - args.get(0), args.get(1), args.get(2)); - default: - return String.format("Range check failed: %s %s", checkKind, args); - } - } - - /** * Checks if the {@code index} is within the bounds of the range from * {@code 0} (inclusive) to {@code length} (exclusive). * * <p>The {@code index} is defined to be out-of-bounds if any of the * following inequalities is true: --- 346,355 ----
*** 524,599 **** * <li>{@code index < 0}</li> * <li>{@code index >= length}</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkIndex(int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param index the index * @param length the upper-bound (exclusive) of the range * @return {@code index} if it is within bounds of the range * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds * @since 9 */ public static int checkIndex(int index, int length) { ! return checkIndex(index, length, null); ! } ! ! /** ! * Checks if the {@code index} is within the bounds of the range from ! * {@code 0} (inclusive) to {@code length} (exclusive). ! * ! * <p>The {@code index} is defined to be out-of-bounds if any of the ! * following inequalities is true: ! * <ul> ! * <li>{@code index < 0}</li> ! * <li>{@code index >= length}</li> ! * <li>{@code length < 0}, which is implied from the former inequalities</li> ! * </ul> ! * ! * <p>If the {@code index} is out-of-bounds, then a runtime exception is ! * thrown that is the result of applying the following arguments to the ! * exception formatter: the name of this method, {@code checkIndex}; ! * and an unmodifiable list integers whose values are, in order, the ! * out-of-bounds arguments {@code index} and {@code length}. ! * ! * @param <X> the type of runtime exception to throw if the arguments are ! * out-of-bounds ! * @param index the index ! * @param length the upper-bound (exclusive) of the range ! * @param oobef the exception formatter that when applied with this ! * method name and out-of-bounds arguments returns a runtime ! * exception. If {@code null} or returns {@code null} then, it is as ! * if an exception formatter produced from an invocation of ! * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used ! * instead (though it may be more efficient). ! * Exceptions thrown by the formatter are relayed to the caller. ! * @return {@code index} if it is within bounds of the range ! * @throws X if the {@code index} is out-of-bounds and the exception ! * formatter is non-{@code null} ! * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds ! * and the exception formatter is {@code null} ! * @since 9 ! * ! * @implNote ! * This method is made intrinsic in optimizing compilers to guide them to ! * perform unsigned comparisons of the index and length when it is known the ! * length is a non-negative value (such as that of an array length or from ! * the upper bound of a loop) ! */ ! @HotSpotIntrinsicCandidate ! public static <X extends RuntimeException> ! int checkIndex(int index, int length, ! BiFunction<String, List<Integer>, X> oobef) { ! if (index < 0 || index >= length) ! throw outOfBoundsCheckIndex(oobef, index, length); ! return index; } /** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} --- 357,376 ---- * <li>{@code index < 0}</li> * <li>{@code index >= length}</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param index the index * @param length the upper-bound (exclusive) of the range * @return {@code index} if it is within bounds of the range * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds * @since 9 */ + @ForceInline public static int checkIndex(int index, int length) { ! return Preconditions.checkIndex(index, length, null); } /** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
*** 606,678 **** * <li>{@code fromIndex > toIndex}</li> * <li>{@code toIndex > length}</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkFromToIndex(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-range * @param toIndex the upper-bound (exclusive) of the sub-range * @param length the upper-bound (exclusive) the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds * @since 9 */ public static int checkFromToIndex(int fromIndex, int toIndex, int length) { ! return checkFromToIndex(fromIndex, toIndex, length, null); ! } ! ! /** ! * Checks if the sub-range from {@code fromIndex} (inclusive) to ! * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} ! * (inclusive) to {@code length} (exclusive). ! * ! * <p>The sub-range is defined to be out-of-bounds if any of the following ! * inequalities is true: ! * <ul> ! * <li>{@code fromIndex < 0}</li> ! * <li>{@code fromIndex > toIndex}</li> ! * <li>{@code toIndex > length}</li> ! * <li>{@code length < 0}, which is implied from the former inequalities</li> ! * </ul> ! * ! * <p>If the sub-range is out-of-bounds, then a runtime exception is ! * thrown that is the result of applying the following arguments to the ! * exception formatter: the name of this method, {@code checkFromToIndex}; ! * and an unmodifiable list integers whose values are, in order, the ! * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. ! * ! * @param <X> the type of runtime exception to throw if the arguments are ! * out-of-bounds ! * @param fromIndex the lower-bound (inclusive) of the sub-range ! * @param toIndex the upper-bound (exclusive) of the sub-range ! * @param length the upper-bound (exclusive) the range ! * @param oobef the exception formatter that when applied with this ! * method name and out-of-bounds arguments returns a runtime ! * exception. If {@code null} or returns {@code null} then, it is as ! * if an exception formatter produced from an invocation of ! * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used ! * instead (though it may be more efficient). ! * Exceptions thrown by the formatter are relayed to the caller. ! * @return {@code fromIndex} if the sub-range within bounds of the range ! * @throws X if the sub-range is out-of-bounds and the exception factory ! * function is non-{@code null} ! * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and ! * the exception factory function is {@code null} ! * @since 9 ! */ ! public static <X extends RuntimeException> ! int checkFromToIndex(int fromIndex, int toIndex, int length, ! BiFunction<String, List<Integer>, X> oobef) { ! if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) ! throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); ! return fromIndex; } /** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code fromIndex + size} (exclusive) is within the bounds of range from --- 383,402 ---- * <li>{@code fromIndex > toIndex}</li> * <li>{@code toIndex > length}</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param fromIndex the lower-bound (inclusive) of the sub-range * @param toIndex the upper-bound (exclusive) of the sub-range * @param length the upper-bound (exclusive) the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds * @since 9 */ public static int checkFromToIndex(int fromIndex, int toIndex, int length) { ! return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null); } /** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code fromIndex + size} (exclusive) is within the bounds of range from
*** 685,755 **** * <li>{@code size < 0}</li> * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkFromIndexSize(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-interval * @param size the size of the sub-range * @param length the upper-bound (exclusive) of the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds * @since 9 */ public static int checkFromIndexSize(int fromIndex, int size, int length) { ! return checkFromIndexSize(fromIndex, size, length, null); } - /** - * Checks if the sub-range from {@code fromIndex} (inclusive) to - * {@code fromIndex + size} (exclusive) is within the bounds of range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - * <p>The sub-range is defined to be out-of-bounds if any of the following - * inequalities is true: - * <ul> - * <li>{@code fromIndex < 0}</li> - * <li>{@code size < 0}</li> - * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> - * <li>{@code length < 0}, which is implied from the former inequalities</li> - * </ul> - * - * <p>If the sub-range is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkFromIndexSize}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code fromIndex}, {@code size}, and - * {@code length}. - * - * @param <X> the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param fromIndex the lower-bound (inclusive) of the sub-interval - * @param size the size of the sub-range - * @param length the upper-bound (exclusive) of the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code fromIndex} if the sub-range within bounds of the range - * @throws X if the sub-range is out-of-bounds and the exception factory - * function is non-{@code null} - * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and - * the exception factory function is {@code null} - * @since 9 - */ - public static <X extends RuntimeException> - int checkFromIndexSize(int fromIndex, int size, int length, - BiFunction<String, List<Integer>, X> oobef) { - if ((length | fromIndex | size) < 0 || size > length - fromIndex) - throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); - return fromIndex; - } } --- 409,426 ---- * <li>{@code size < 0}</li> * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param fromIndex the lower-bound (inclusive) of the sub-interval * @param size the size of the sub-range * @param length the upper-bound (exclusive) of the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds * @since 9 */ public static int checkFromIndexSize(int fromIndex, int size, int length) { ! return Preconditions.checkFromIndexSize(fromIndex, size, length, null); } }
< prev index next >