[英]Why does the Double.valueof javadoc say it caches values, when it doesn't?
在OpenJDK中,该方法为:
public static Double valueOf(double d)
Javadoc说:
返回表示指定double值的Double实例。 如果不需要新的Double实例,则通常应优先于构造方法Double(double)使用此方法,因为此方法通过缓存经常请求的值可能会产生明显更好的空间和时间性能。
这是实际的代码:
public static Double valueOf(double d) {
return new Double(d);
}
缓存是骗人的! 这里发生了什么?
该方法存在多种类型: Integer
, Long
, BigDecimal
和其他类型,并且文档始终相同:在某些情况下(未定义),该方法可以返回相同的结果。
AFAIK,仅对整数类型实现缓存,并且它返回值介于-128到127(最常见的值)之间的缓存实例。 对于BigDecimal
,缓存当前适用于0到10的值。
Java的更高版本可能将此行为扩展到其他值/更多类型。 因此,今天使用此代码很明智,因为这可能会使您的代码明天更快(并且今天的代码不会太慢)。
例如,Java编译器在生成自动装箱代码时使用此API。
API文档没有错:
这种方法可能会产生...
就是说,允许实现在这里进行缓存,而构造函数根本不可能实现。 但是,这不是必需的。 但是,由于您可能有一个执行缓存的实现,因此与使用构造方法相比,应首选此方法。
从Java 1.5+开始,JVM / JIT保证将Integer
s -127缓存到127。因此,对于Integer
,首选方法是使用valueOf
。 通常,应该使用valueOf
不是将构造函数用于double
因为JIT可以根据需要优化代码。 例如,考虑以下循环:
for (Object o: objectList) {
o.setValue(Double.valueOf(0.0));
}
在这种情况下,JIT可以预先计算double对象,并在循环的每次迭代中重新分配相同的值,而如果要使用new Double(0.0);
它将无法做到这一点。
API的设计者可能不想限制替代实现。 现在,它们可以自由地将缓存添加到Double
类中。
这些valueOf()
方法存在于每种数字类型中,以支持缓存。 实际上,对于Double来说,它不使用任何缓存,而对于Integer
和Long
,则不使用任何缓存。
请记住,创建JVM是为了减少嵌入式设备的代码大小(大多数情况下),它是一个机顶盒操作系统。 我已经在一些嵌入式Java平台上工作,在那些平台上,valueOf的“ value”将更加明显,在某些情况下,它将节省大量空间。
通常存在该方法是因为“新”永远无法使用缓存的实例。 可以实现valueOf以使用缓存的实例(否则,您将始终使用new),并且可能在证明可以节省时间的任何地方进行。
如果他们(或您)用实际缓存值的方法代替了该方法,那么您的所有代码都将获得该更改的优势,但是如果不通过提供诸如“ valueOf”之类的方法进行准备,它就永远不会发生(嗯,实际上永远不会-您可以调整编译器/字节码执行器以使“新”返回缓存值,但我认为这会破坏某些合同)
因此,缓存并不是真正的谎言,只是一种心理状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.