如何解决为什么 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
值索引; short
、byte
或 char
值也可以用作索引值,因为它们经过一元数字提升(第 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 举报,一经查实,本站将立刻删除。