我正在检查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
值索引;short
、byte
或char
值也可以用作索引值,因为它们经过一元数字提升(§5.6)并变成int
值。
尝试使用long
索引值访问数组组件会导致编译时错误。
什么时候使用这个long
索引构造函数或者为什么需要它?
我在OpenJdk中找到了另一个与该更改相关的票证。如其中所述
明确地编写边界检查并不难,但它很容易犯一些小错误,比如引入溢出错误。从正确性和安全性/完整性的角度合并这些检查是有利的。此外,在某些情况下,它是一个优化的机会,通过一个内在的,某些检查和引导热点到无符号比较。
对Java平台的增强将使循环能够在大于int值的最小和最大范围的边界上进行优化,这需要对长值进行边界检查。
在外部内存访问API(JEP 393)中,内存段的界限表示为长值。由于涉及长的绑定检查目前还没有得到优化,因此外部内存访问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问题:添加实用程序方法来检查长索引和范围
引用备查意见:
这是由Project Panama促成的,它为Java提供了更好的本地堆访问。外部内存API(直接字节缓冲区的替换)允许对本机内存段进行长索引的堆访问,从而将此更改转化为IOOBE。--布莱恩·戈茨
它与以下特性增强(JDK-8255150)有关:添加用于检查长索引和范围的实用程序方法
说明
这与JDK-8135248有关。目标是添加一组类似的方法,但新方法不是对int参数进行操作,而是对长参数进行操作。
对象中的新方法有:
公共静态long checkIndex(long index,long length)公共静态long checkFromToIndex(long fromIndex,long toIndex,long length)公共静态long checkFromToIndex(long fromIndex,long size,long length)
它们镜像int实用程序方法。
与int checkIndex()的情况一样,长checkIndex()方法将被JIT编译为内部的。这允许JIT将checkIndex编译为无符号比较,并将其正确识别为范围检查,然后将其作为现有范围检查优化的候选项。这已经证明对巴拿马的MemorySegment很重要,并且这个改变的原型(有一些额外的c2改进)表明巴拿马的微基准测试结果显著改善。
关于这个主题的另一个来源:JDK 16:检查索引和长的范围:
在我的上一篇文章中,我描述了JDK16早期访问Build25中添加的日周期支持。该版本还添加了检查长值的索引和范围的方法,这也是本文的主题。JDK-8255150(“add utility methods to check long indexes and Rangement”)是用于添加用于检查long indexes和Rangement的实用工具方法的增强功能,类似于JDK-8135248(“add utility methods to check indexes and Rangement”)在JDK9中为整数添加的功能。JDK-8255150指出,“目标是添加一组类似的方法[如JDK-8135248],但新方法不是对int参数进行操作,而是对长参数进行操作。”
这些新添加的长支持方法的最大受益者可能是外部内存访问API的作者、维护人员和用户,如以下邮件列表中所述:“为了利用基于int的索引检查的内在特性,我们必须跳过外部内存访问API的实现过程中的许多环节,即使这样,我们也不涉及数字大于int的情况。期待着能够移除那些黑客!“
类有2个构造函数 oracle的第二个构造函数的描述如下 谁能解释一下?
问题内容: 为什么Java 中的类有一个? 我们无法实例化一个类,它的构造是什么? 有什么想法吗? 问题答案: Java中的构造函数实际上并不“构建”对象,而是用于初始化字段。 想象一下,您的抽象类具有字段x和y,并且无论最终创建什么实际的具体子类,您总是希望以某种方式对其进行初始化。因此,您将创建一个构造函数并初始化这些字段。 现在,如果您的抽象类有两个不同的子类,则在实例化它们时,将调用它们的
问题内容: 如果不可变的类对象副本将与原始副本相等,那么为什么Java 中的类具有副本构造函数?这是一个错误还是背后有原因?在Java文档中,指定了: 问题答案: 复制字符串的主要原因是为了 “修剪行李” ,即仅将底层char数组修剪为必需的字符。 基本的char数组可能太大,因为通过调用创建字符串时,char数组可以在新的字符串实例和源字符串实例之间共享;偏移量指向第一个字符,并且包括长度。 我
问题内容: Java 构造函数的文档说明: 注意:很少适合使用此构造函数。除非需要新实例,否则静态工厂通常是更好的选择。它可能会产生明显更好的时空性能。 如果是这样,为什么这个构造函数是公开的而不被弃用?是否有充分的理由使用此构造函数代替? 问题答案: Java 1.4中仅添加了它,因此似乎存在构造函数是为了向后兼容。 此票证解释了不弃用构造函数的原因: 由于该中断,API可能不推荐使用,因此,当
问题内容: 由于枚举构造函数只能由其常量调用,因此为什么要允许它成为包私有的? 问题答案: 构造函数实际上不是包私有的…隐式地意味着接口方法是隐式的,即使您不添加关键字也是如此。 JLS(第8.8.3节)的相关部分规定: 如果没有为普通类的构造函数指定访问修饰符,则该构造函数具有默认访问权限。 如果没有为枚举类型的构造函数指定访问修饰符,则构造函数为。 如果枚举类型(第8.9节)的构造函数声明为或
问题内容: 我找不到确切的答案。据我所知,类中不能有多个功能。那么我该如何解决这个问题呢? 假设我有一个Cheese用属性调用的类。我如何有两种创建奶酪对象的方式… 有很多这样的漏洞: 还有一个不带参数而只是随机化属性的参数: 我只能想到一种执行此操作的方法,但这似乎很笨拙: 你说什么?还有另一种方法吗? 问题答案: 对于“魔术”值,实际上要好得多: 现在,如果你想完全自由地添加更多参数: 为了更