29

我正在检查 JDK 16 中IndexOutOfBoundsException的实现,我注意到long引入了一个带有索引的新构造函数:

/**
 * Constructs a new {@code IndexOutOfBoundsException} class with an
 * argument indicating the illegal index.
 *
 * <p>The index is included in this exception's detail message.  The
 * exact presentation format of the detail message is unspecified.
 *
 * @param index the illegal index.
 * @since 16
 */
public IndexOutOfBoundsException(long index) {
    super("Index out of range: " + index);
}

据我所知,数组索引通常是int值,这在语言规范第 10.4 节中得到了证实:

数组必须按int值索引;shortbytechar值也可以用作索引值,因为它们受到一元数字提升(第 5.6 节)并成为int值。

尝试使用long索引值访问数组组件会导致编译时错误。

知道何时(以及为什么)long使用此索引构造函数吗?

4

3 回答 3

29
于 2021-03-17T13:14:45.217 回答
14

我在 OpenJdk 中找到了另一个与该更改相关的 Ticket。如那里所述

明确编写边界检查并不难,但很容易犯一些小错误,例如引入溢出错误。从正确性和安全性/完整性的角度整合这些检查是有利的。此外,在某些情况下,它是通过内在的某些检查优化并引导热点进行无符号比较的机会。

对 Java 平台的增强将能够优化超出 int 值的最小和最大范围的循环,需要对 long 值进行边界检查。

在外部内存访问 API (JEP 393) 中,内存段的边界表示为长值。由于涉及 long 的绑定检查目前尚未优化,因此外部内存访问 API 的实现必须借助一些技巧来判断内存段是否可以被视为“小”(例如,其大小适合 int 值),然后使用 int相应地,对小段进行操作。虽然在大多数情况下,这些变通办法隐藏在 API 实现中,但它们在复杂性和长期维护方面增加了巨大的成本。

解决方案 用长接受边界检查方法重载 java.util.Objects 中定义的现有 int 接受边界检查方法。

java.util.Objects 中添加了以下静态方法。该规范与现有的具有相同方法名称的 int 接受边界检查方法的规范相同。

/**
 * 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>
 *
 * @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 16
 */
public static
long checkIndex(long index, long length)

/**
 * 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>
 *
 * @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 16
 */
public static
long checkFromToIndex(long fromIndex, long toIndex, long length)

/**
 * 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>
 *
 * @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 16
 */
public static
long checkFromIndexSize(long fromIndex, long size, long length)

将以下构造函数添加到 java.lang.IndexOutOfBoundsException:

/**
 * Constructs a new {@code IndexOutOfBoundsException} class with an
 * argument indicating the illegal index.
 *
 * <p>The index is included in this exception's detail message.  The
 * exact presentation format of the detail message is unspecified.
 *
 * @param index the illegal index.
 * @since 16
 */
public IndexOutOfBoundsException(long index)

Jira 问题:添加实用程序方法来检查长索引和范围

于 2021-03-17T14:00:08.137 回答
7

AnIndexOutOfBoundsException不一定只在访问数组时抛出(有它的子类ArrayIndexOutOfBoundsException)或 a List; 您可以从您自己的任何代码中抛出它,并且允许用户编写的类或第三方库抛出似乎是合理的,IndexOutOfBoundsException即使它们的索引是long而不是int.

于 2021-03-17T22:06:12.833 回答