繁体   English   中英

为什么在Integer类的Integer.valueOf方法中使用assert?

[英]Why is assert used in the Integer.valueOf method of the Integer class?

我正在研究Integer类如何实际使用缓存对象,我在Integer.valueOf方法中找到了以下代码:

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

我的问题是:

断言的目的是建立不变量并记录实现。 在这里,这个断言记录了这样一个事实,当进入valueOf方法时, IntegerCache.high值保证至少为 127。最好写一个断言而不是注释,因为当相应的断言时,JVM 也会检查断言命令行选项 ( -esa ) 处于活动状态。

通常这个断言永远不会抛出,因为IntegerCache.high是这样初始化的:

int h = 127;
String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
    try {
        int i = parseInt(integerCacheHighPropValue);
        i = Math.max(i, 127);
        // Maximum array size is Integer.MAX_VALUE
        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    } catch( NumberFormatException nfe) {
        // If the property cannot be parsed into an int, ignore it.
    }
}
high = h;

此代码保证该值至少为 127。因此,如果您修改IntegerCache.high (使用反射和setAccessible(true) )或者如果将来会修改 JDK 并且 IntegerCache 中将引入错误,则断言可能会抛出IntegerCache.high初始化代码。 这就是断言存在的原因:捕捉错误。

JLS 要求整数缓存必须用于 -128 到 127 之间的整数。

目前,Oracle 实现会强制执行此操作,但不会再执行此操作,因此缓存上限很可能会在将来的某个时候扩展(在实践中不太可能,但完全符合规范。)

但是,它永远不能小于127,否则实现将不再符合 JLS - 这将是一件大事,因此(我相信)为什么会有 assert 语句!

正如 biziclop 在评论中指出的那样,用户也可以通过传递 VM 参数来更改它 - 另一个(也许更引人注目)断言的原因。

另请注意,除非使用-ea运行,否则将跳过断言语句,因此在正常使用中,此检查绝对没有运行时开销。

缓存,通常为 -128 ... 127,可以扩大,这可能是原因:它不应该变得更少。 由于代码即使没有缓存也能运行,所以断言可能是一种软方式:在开发时报告性能缺陷。 As 断言对生产代码没有影响。

看着

http://www.docjar.com/html/api/java/lang/Integer.java.html

我看到这个评论

       /*
        * WARNING: This method may be invoked early during VM initialization
        * before IntegerCache is initialized. Care must be taken to not use
       * the valueOf method.
       */

如果他们在parseInt使用了valueOf ,那么当parseInt在 VM 初始化的早期被调用时, high值实际上将为零。

我不确定这会导致什么问题,但显然有人认为值得警惕。

  1. assert IntegerCache.high >= 127 有什么用; 我读到断言提供了一种检测和纠正编程错误的有效方法。 但这是运行时代码,为什么有人会使用断言?

防止在 VM 初始化期间调用 valueOf 方法调用的代码。

  1. 在这种情况下它什么时候会抛出 AssertionError ?

如果您使用 -ea 选项(启用断言)运行 java 并且有一些调用 valueOf 的初始化代码,JVM 几乎会立即崩溃,因为 AssertionError。 希望 Java 团队测试这些东西,并在将其发布到野外之前修复有问题的代码。

与其他答案的断言相反,high 总是大于或等于 128,它似乎有时为零(不计算反射)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM