55

In OpenJDK, for the method:

public static Double valueOf(double d)

The javadoc says:

Returns a Double instance representing the specified double value. If a new Double instance is not required, this method should generally be used in preference to the constructor Double(double), as this method is likely to yield significantly better space and time performance by caching frequently requested values.

Here's the actual code:

public static Double valueOf(double d) {
    return new Double(d);
}

The cache is a lie! What's going on here?

z7sg Ѫ
  • 3,153
  • 1
  • 23
  • 35
  • 32
    The documentation is always wrong. Remember that. – Dave Newton Dec 19 '11 at 13:10
  • 5
    Where do you take the code from anyways? OpenJDK6? OpenJDK7? Apache Harmony? GNU Classpath? – scravy Dec 19 '11 at 13:23
  • @scravy I'm looking at OpenJDK7 but this code hasn't changed for years in the official Sun releases. – z7sg Ѫ Dec 19 '11 at 13:27
  • 28
    +1 the cache is a lie – Chris Burt-Brown Dec 19 '11 at 14:45
  • 4
    Note the word "likely" in the documentation. If you take the sentence after that (including "by...values") as one entity, it doesn't say anything about a promise, but more about a possibility. Instead of "is likely to" a better wording could've been "might". – Abel Dec 19 '11 at 15:32
  • 3
    Seems clear that "is likely" refers to the better performance, not the caching. – Chad Schouggins Dec 20 '11 at 18:20
  • The only truth is in code, not in comments (and in fact, even the code may not be correct, depending on how it's run. The runtime environment / JDK might, in this case, cache the Double value internally somewhere. You know, like it does with Strings.) – cthulhu Dec 24 '11 at 12:22

6 Answers6

58

The method exists for many types: Integer, Long, BigDecimal and others and the documentation is always the same: Under some circumstances (which aren't defined), the method can return the same result.

AFAIK, the caching is only implemented for integer types and it returns cached instances for values between -128 and 127 (most common values). For BigDecimal, the cache currently works for values from 0 to 10.

Later versions of Java might extend this behavior to other values/more types. So it's smart to use this code today because it might make your code faster tomorrow (and the code won't be slower today).

The Java compiler, for example, uses this API when generating code for autoboxing.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
30

There is nothing wrong with the API doc:

This method is likely to yield...

That is, an implementation is allowed to do caching here, which is simply not possible with a constructor. However, it is not required to. But, since chances are that you have an implementation that performs caching, this method should be preferred over using a constructor.

scravy
  • 11,904
  • 14
  • 72
  • 127
  • 4
    +1. IMHO, the key point is that the OP writes of "*the* actual code", but what (s)he supplies is just *one* implementation. Other implementations can and do exist for other platforms. (In particular, it wouldn't surprise me to see a difference here in a firmware implementation.) – ruakh Dec 19 '11 at 13:19
  • @ruakh I would have thought an alternative implementation would also come with alternative javadoc. The code and javadoc go together, it's not supposed to be a high-level specification document. That would not belong with the code. – z7sg Ѫ Dec 19 '11 at 13:24
  • 7
    The javadoc of the java.* classes *are* specifications, as other their are vendors other than Oracle which write Java implementations and they have to provide the same functionality for all these classes. – Mark Rotteveel Dec 19 '11 at 13:30
  • @MarkRotteveel No they are free to provide different functionality if they choose to. They don't have to implement java.* classes at all, if they don't want to. And if you check the javadoc for those different implementations, you will see that it is... different. – z7sg Ѫ Dec 19 '11 at 13:53
  • 5
    No, to conform with Java you have to implement the functionality of the standard library which is specified in the official API doc. Of course you could build a JVM with another class library, but that's simply not java, but a JVM. – scravy Dec 19 '11 at 13:55
  • @scravy You have to conform to the JSRs, not to what's in the javadoc. – z7sg Ѫ Dec 19 '11 at 14:28
  • 1
    @z7sgѪ The first letters in the apidoc read: “This document is the API specification for version 6 of the Java™ Platform, Standard Edition.” – scravy Mar 18 '12 at 22:28
12

From Java 1.5+, the JVM/JIT guarantees the caching of Integers -127 to 127. So that is why for Integer the preferred approach is to use valueOf. You should generally use valueOf over using the constructor for double because then the JIT is able to optimise your code as it sees fit. For example, consider the following loop:

for (Object o: objectList) {
  o.setValue(Double.valueOf(0.0));
}

In this instance, the JIT can precalculate the double object and reassign the same value on each iteration of the loop, whereas if you were to use new Double(0.0); it would not be able to do that.

user
  • 6,897
  • 8
  • 43
  • 79
Deco
  • 3,261
  • 17
  • 25
7

The designers of the API probably didn’t want to restrict alternate implementation. Those are now free to add caching to the Double class.

Bombe
  • 81,643
  • 20
  • 123
  • 127
2

These valueOf() methods exist in every numeric type for the purpose to support caching. In fact, for Double it does not use any cache but for Integer and Long.

Fabian Barney
  • 14,219
  • 5
  • 40
  • 60
2

Remember that the JVM was created to reduce code size for embedded devices (mostly)--it's a set-top box operating system. I've worked on a few embedded java platforms and on those the "value of" valueOf would be more obvious, it would save quite a bit of space in some cases.

Mostly the method exists because "new" cannot ever use cached instances. valueOf MAY be implemented to use cached instances (otherwise you would just always use new) and likely does wherever it proves to save time.

If they (or you) replaced that method with one that actually did cache values then all your code would gain the advantage of that change, but without preparing by providing a method like "valueOf" it could never happen (well, practically never--you could tweak the compiler/bytecode executor to have "new" return cached values but I think that would break some contracts)

So the cache isn't really a lie, just a state of mind.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • 2
    Can you give a reference to the statement about the reason for the jvm? The valueOf methods are new, to support autoboxing. There should never have been constructors for these, this in particular goes for Boolean. – stolsvik Dec 21 '11 at 21:41