Подтвердить что ты не робот

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

В OpenJDK для метода:

public static Double valueOf(double d)

В javadoc говорится:

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

Вот фактический код:

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

В документе API нет ничего плохого:

Этот метод, вероятно, даст...

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

Итак, кеш - это не ложь, а только состояние ума.