Почему делает дубль.valueof javadoc говорит, что он кэширует значения, когда это не так?


в OpenJDK, для метода:

public static Double valueOf(double d)

javadoc говорит:

возвращает двойной экземпляр, представляющий указанное двойное значение. Если новый экземпляр Double не требуется, этот метод обычно следует использовать в предпочтении к конструктору Double (double), так как этот метод, вероятно, даст значительно лучшую производительность пространства и времени путем кэширования часто запрашиваемых значений.

вот собственно код:

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

кэш-это ложь! Что здесь происходит?

6 52

6 ответов:

метод существует для многих типов:Integer,Long,BigDecimal и другие, и документация всегда одна и та же: при некоторых обстоятельствах (которые не определены), метод можете возвращает тот же результат.

AFAIK, кэширование реализовано только для целочисленных типов и возвращает кэшированные экземпляры для значений между -128 и 127 (наиболее распространенные значения). Ибо BigDecimal кэш в настоящее время работает для значений от 0 до 10.

более поздние версии Java может распространите это поведение на другие значения / другие типы. Поэтому разумно использовать этот код сегодня, потому что это может сделать ваш код быстрее завтра (и код не будет медленнее сегодня).

компилятор Java, например, использует этот API при создании кода для автобоксинга.

нет ничего плохого в API doc:

этот метод вероятно выход...

то есть, реализация позволяет делать кэширование здесь, что просто невозможно с конструктором. Однако этого и не требуется. Но, поскольку есть вероятность, что у вас есть реализация, которая выполняет кэширование, этот метод следует предпочесть использованию конструктора.

из Java 1.5+, JVM / JIT гарантирует кэширование Integers -127 до 127. Так вот почему для Integer предпочтительный подход заключается в использовании valueOf. Обычно вы должны использовать valueOf С помощью конструктора для double потому что тогда JIT может оптимизировать ваш код, как он считает нужным. Например, рассмотрим следующий цикл:

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

в этом случае JIT может предварительно вычислить двойной объект и переназначить одно и то же значение на каждой итерации цикла, тогда как если вы должны использовать new Double(0.0); он не сможет этого сделать.

разработчики API, вероятно, не хотели ограничивать альтернативную реализацию. Теперь они могут добавить кэширование в Double класса.

эти valueOf() методы существуют в каждом числовом типе для поддержки кэширования. На самом деле, для Double он не использует никакого кэша, но для Integer и Long.

помните, что JVM был создан для уменьшения размера кода для встроенных устройств (в основном)-это операционная система с приставкой. Я работал на нескольких встроенных платформах java, и на них "значение" valueOf было бы более очевидным, в некоторых случаях это сэкономило бы довольно много места.

в основном метод существует, потому что" new " никогда не может использовать кэшированные экземпляры. valueOf может быть реализован для использования кэшированных экземпляров (в противном случае вы просто всегда будете использовать new) и, вероятно, делает везде, где это доказывает, что экономит время.

если они (или вы) заменили этот метод на тот, который на самом деле кэшировал значения, тогда весь ваш код получит преимущество этого изменения, но без подготовки, предоставив метод, подобный "valueOf", это никогда не произойдет (ну, практически никогда-вы можете настроить компилятор/исполнитель байт-кода, чтобы иметь "новые" возвращаемые кэшированные значения, но я думаю, что это нарушит некоторые контракты)

Так что кэш на самом деле не ложь, просто состояние ума.