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

Vis*_*ant 26 java assert integer

我正在深入研究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);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

Tag*_*eev 17

断言的目的是建立不变量并记录实现.在这里,这个断言记录了这样一个事实:当输入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;
Run Code Online (Sandbox Code Playgroud)

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

  • 如果在IntegerCache.high等于0的VM初始化期间调用它,则assert也可以抛出. (2认同)

Mic*_*rry 9

JLS要求整数缓存必须适用于-128和127之间的整数.

目前,Oracle实现强制执行此操作但不再执行,因此缓存上限可能会在未来的某个时间点延长(实际上不太可能,但它完全符合规范).

但是,它永远不会少于 127,否则实现将不再符合JLS - 这将是一个相当大的交易,因此(我相信)为什么断言声明存在!

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

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

  • 从Java 7开始,它是`-Djava.lang.Integer.IntegerCache.high = <size>`.在此之前,没有断言,因为缓存确实是固定的. (4认同)
  • 您实际上可以从命令行指定缓存大小. (2认同)

Joo*_*gen 6

缓存,通常为-128 ... 127,可以放大,这可能是原因:它不应该变得更少.而且,即使没有缓存,代码也能正常工作,断言可能是一种软性方式:在开发时告诉性能缺陷.断言对生产代码没有影响.

  • 断言确保代码符合JLS,JLS明确要求缓存至少为该大小. (3认同)