Почему Double.value of javadoc говорит, что он кэширует значения, тогда как это не так? - PullRequest
53 голосов
/ 19 декабря 2011

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

public static Double valueOf(double d)

Javadoc говорит:

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

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

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

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

Ответы [ 6 ]

54 голосов
/ 19 декабря 2011

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

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

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

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

29 голосов
/ 19 декабря 2011

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

Этот метод может дать ...

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

12 голосов
/ 19 декабря 2011

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

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

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

6 голосов
/ 19 декабря 2011

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

2 голосов
/ 19 декабря 2011

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

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

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

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

2 голосов
/ 19 декабря 2011

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

...