If we take a look at the javaSE 6 source code we can see that the Long class for instance creates a cache inside the static block of an inner class:
private static class LongCache {
private LongCache() { }
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) {
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
The main difference is that new will always return a brand new instance whereas the valueOf method may return an “old” object that has been created and cached in advance. The downside of this approach is that the first call of valueOf will create all instance for the cache.
The Double and Float wrapper classes just call new inside the valueOf method. There is no sign of any caching at all in their implementation. All other wrapper classes (Byte, Character, Boolean, ...) have a caching mechanism similar to the example above.