为什么Double.valueof javadoc说它缓存值,当它没有?

z7s*_*g Ѫ 53 java javadoc

在OpenJDK中,对于方法:

public static Double valueOf(double d)
Run Code Online (Sandbox Code Playgroud)

javadoc说:

返回表示指定double值的Double实例.如果不需要新的Double实例,通常应优先使用此方法,而不是构造函数Double(double),因为此方法可能通过缓存频繁请求的值来显着提高空间和时间性能.

这是实际的代码:

public static Double valueOf(double d) {
    return new Double(d);
}
Run Code Online (Sandbox Code Playgroud)

缓存是谎言!这里发生了什么?

Aar*_*lla 55

该方法适用于多种类型:Integer,和其他类型Long,BigDecimal并且文档始终相同:在某些情况下(未定义),该方法可以返回相同的结果.

AFAIK,缓存仅针对整数类型实现,并且返回介于-128和127之间的值的缓存实例(最常见的值).因为BigDecimal,缓存当前适用于0到10之间的值.

更高版本的Java 可能会将此行为扩展到其他值/更多类型.因此,今天使用此代码是明智的,因为它可能使您的代码明天更快(并且代码今天不会变慢).

例如,Java编译器在生成自动装箱代码时使用此API.


scr*_*avy 29

API文档没有任何问题:

这种方法可能会产生......

也就是说,允许实现在这里进行缓存,这对于构造函数来说是不可能的.但是,它不是必需的.但是,由于您可能有一个执行缓存的实现,因此该方法应优先于使用构造函数.

  • java.*classes*的javadoc是*规范,因为除了Oracle以外的其他供应商编写Java实现,他们必须为所有这些类提供相同的功能. (7认同)
  • 不,为了符合Java,您必须实现官方API文档中指定的标准库的功能.当然你可以用另一个类库构建一个JVM,但这不是java,而是一个JVM. (5认同)
  • +1.恕我直言,关键点在于OP写了"*the*actual code",但他提供的是***实现.其他实现可以并且确实存在于其他平台.(特别是,在固件实现中看到差异并不会让我感到惊讶.) (4认同)

Dec*_*eco 12

从Java 1.5+开始,JVM/JIT保证将Integers -127 缓存到127.这就是为什么Integer首选方法是使用valueOf.您通常应该使用valueOf构造函数,double因为JIT能够在其认为合适时优化您的代码.例如,考虑以下循环:

for (Object o: objectList) {
  o.setValue(Double.valueOf(0.0));
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,JIT可以预先计算双重对象,并在循环的每次迭代中重新分配相同的值,而如果你要使用new Double(0.0);它将无法做到这一点.

  • 恭喜,你现在有2013年代表,新年快乐2013 :) (2认同)

Bom*_*mbe 6

API的设计者可能不希望限制替代实现.现在可以自由地为Double课程添加缓存.