微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 IndexOutOfBoundsException 现在在 Java 16 中有一个带有长索引作为参数的构造函数?

如何解决为什么 IndexOutOfBoundsException 现在在 Java 16 中有一个带有长索引作为参数的构造函数?

我正在检查 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 值,这在 Language Specification section §10.4 中得到证实:

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

尝试访问具有 long 索引值的数组组件会导致编译时错误

知道什么时候(以及为什么)会使用这个 long 索引构造函数吗?

解决方法

引用评论以供将来参考:

这是由 Project Panama 促成的,它带来了更好的原生 Java 的堆访问。外部内存 API(直接替代 字节缓冲区)允许长索引堆访问本机内存 段,促使这一变化为 IOOBE。 – 布赖恩·戈茨

TL;DR 它与以下功能增强 (JDK-8255150) 相关:Add utility methods to check long indexes and ranges

说明
这与 JDK-8135248 相关。 目标是添加一个 类似的方法集,但不是对 int 参数进行操作, 新方法对长参数进行操作。

对象中的新方法是:

public static long checkIndex(long index,long length) public static long checkFromToIndex(long fromIndex,long toIndex,long length) public static long checkFromIndexSize(long fromIndex,long size,long 长度)

它们反映了 int 实用程序方法。

与 int checkIndex() 一样,long checkIndex() 方法 将被 JIT 编译为内在函数。这允许 JIT 编译 checkIndex 到一个无符号的比较并正确地将其识别为 范围检查然后成为现有范围检查的候选者 优化。事实证明,这对巴拿马的 MemorySegment 和此更改的原型(带有一些额外的 c2 改进)表明巴拿马微基准测试结果有所改善 显着。

来自关于该主题的另一个来源:JDK 16: Checking Indexes and Ranges of Longs

在我的上一篇文章中,我描述了 JDK 16 添加的日间周期支持 Early Access Build 25。同一个版本还添加了检查方法 长值的索引和范围,这是本文的主题。 JDK-8255150(“添加实用方法来检查长索引和范围”) 是用于添加用于检查长的实用方法的增强 索引和范围类似于 JDK-8135248(“添加实用方法 检查索引和范围”)为 JDK 9 添加的整数。 JDK-8255150 指出,“目标是添加一组类似的方法 [如 JDK-8135248] 但不是对 int 参数进行操作,而是新方法 对长参数进行操作。”

这些新增长养方法的最大受益者 可能是外部记忆的作者、维护者和用户 访问此邮件列表消息中描述的 API:“我们必须跳转 通过相当多的箍在执行外部内存 访问 API 以利用基于 int 的内在化 索引检查,即使这样我们也没有涵盖 数字大于整数。期待能够删除 那些黑客!”

,

我在 OpenJdk 中找到了另一个与该更改相关的票证。如上所述

边界检查不难显式编写,但可以 容易犯一些小错误,例如引入溢出错误。它 有利于从正确性和 安全/完整性观点。此外,在某些情况下,它是一个 通过内在的某些检查和指南进行优化的机会 无符号比较的热点。

Java 平台的增强将支持循环优化 越界大于 int 值的最小和最大范围, 需要对长值进行边界检查。

在外部内存访问 API (JEP 393) 中,内存的边界 段表示为长值。由于边界检查涉及 longs目前没有优化,国外的执行 内存访问 API 不得不求助于几个技巧来判断一个 内存段可以被认为是“小”的(例如,其大小适合 int 值),然后相应地对小段使用 int 操作。 虽然在大多数情况下,这些解决方法隐藏在 API 中 实施,它们在复杂性和 长期维护。

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

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 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 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 问题:Add utility methods to check long indexes and ranges

,

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。