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

我正在深入研究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); } 

我的问题是:

  • assert IntegerCache.high >= 127;的用途是什么assert IntegerCache.high >= 127; 我读到断言提供了一种检测和纠正编程错误的有效方法 。 但这是运行时代码所以为什么有人会使用assert?
  • 什么时候会在这种情况下抛出AssertionError

断言的目的是建立不变量并记录实现。 在这里,这个断言记录了这样一个事实:当输入valueOf方法时, IntegerCache.high值保证至少为127.最好编写一个assert而不是注释,因为断言也将由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 (使用reflection和setAccessible(true) ),或者将来将修改JDK并且将在IntegerCache.high引入错误,则assert可以抛出IntegerCache.high初始化代码。 这就是断言存在的原因:捕获错误。

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

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

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

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

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

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

看着

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 ,那么当在VM初始化的早期调用parseInt时, high值实际上为零。

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

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

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

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

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

与其他答案的断言相反,高位将始终大于或等于128,似乎有时它为零(不计算reflection)。