Java Double.valueOf - PullRequest
       90

Java Double.valueOf

11 голосов
/ 14 июля 2020

В моей работе все разработчики используют Double.valueOf вместо new Double конструктора. В любом случае. Для Integer или Short я могу понять это для значений кеша, но не для double и float.

Я смотрю Double.valueOf в источниках OpenJDK :

 /**
 * Returns a {@code Double} instance representing the specified
 * {@code double} value.
 * If a new {@code Double} instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Double(double)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * @param  d a double value.
 * @return a {@code Double} instance representing {@code d}.
 * @since  1.5
 */
public static Double valueOf(double d) {
    return new Double(d);
}

Значит, он просто вызывает конструктор Double. Я могу понять, почему метод существует для согласования с Integer / Short ...

Но комментарий к методу:

этот метод обычно следует использовать в предпочтении конструктору

После того, как я увижу тот же комментарий к каждому valueOf() методу. (Целое, Короткое ...)

Комментарий ложный? Или другое вмешательство в процесс?

Я слышал о методах intrinsi c в Java, следующим шагом был поиск в коде точки доступа и vmSymbol.hpp

/* boxing methods: */                                                                                                 \
   do_name(    valueOf_name,              "valueOf")                                                                    \
  do_intrinsic(_Boolean_valueOf,          java_lang_Boolean,      valueOf_name, Boolean_valueOf_signature, F_S)         \
   do_name(     Boolean_valueOf_signature,                       "(Z)Ljava/lang/Boolean;")                              \
  do_intrinsic(_Byte_valueOf,             java_lang_Byte,         valueOf_name, Byte_valueOf_signature, F_S)            \
   do_name(     Byte_valueOf_signature,                          "(B)Ljava/lang/Byte;")                                 \
  do_intrinsic(_Character_valueOf,        java_lang_Character,    valueOf_name, Character_valueOf_signature, F_S)       \
   do_name(     Character_valueOf_signature,                     "(C)Ljava/lang/Character;")                            \
  do_intrinsic(_Short_valueOf,            java_lang_Short,        valueOf_name, Short_valueOf_signature, F_S)           \
   do_name(     Short_valueOf_signature,                         "(S)Ljava/lang/Short;")                                \
  do_intrinsic(_Integer_valueOf,          java_lang_Integer,      valueOf_name, Integer_valueOf_signature, F_S)         \
   do_name(     Integer_valueOf_signature,                       "(I)Ljava/lang/Integer;")                              \
  do_intrinsic(_Long_valueOf,             java_lang_Long,         valueOf_name, Long_valueOf_signature, F_S)            \
   do_name(     Long_valueOf_signature,                          "(J)Ljava/lang/Long;")                                 \
  do_intrinsic(_Float_valueOf,            java_lang_Float,        valueOf_name, Float_valueOf_signature, F_S)           \
   do_name(     Float_valueOf_signature,                         "(F)Ljava/lang/Float;")                                \
  do_intrinsic(_Double_valueOf,           java_lang_Double,       valueOf_name, Double_valueOf_signature, F_S)          \
   do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")       

Итак, после того, как я grep Double.valueOf в источнике и нашел withebox. cpp

static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
  return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}

и код метода коробки:

template <typename T>
static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
  ResourceMark rm(thread);
  jclass clazz = env->FindClass(name->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  jmethodID methodID = env->GetStaticMethodID(clazz,
        vmSymbols::valueOf_name()->as_C_string(),
        sig->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
  CHECK_JNI_EXCEPTION_(env, NULL);
  return result;
}

и это code ...

Хорошо, я еще не продвинулся. Этот метод box () действительно вызывается в режиме сервера?

3 вопроса для возобновления: D

  1. JVM-перехват Double.valueOf() для вызова этого метода box?

  2. Double.valueOf не использует исходный код JDK и не использует new Double()?

  3. Комментарий к Double.valueOf() является просто копией дампа / вставить, Double.valueOf и new Double имеют одинаковый эффект?

Ответы [ 2 ]

10 голосов
/ 14 июля 2020
  1. Integer(int), Double(double) и аналогичные конструкторы устарели (да, они фактически помечены как @Deprecated), поскольку Java 9 как часть JEP 277 .

    Комментарий об устаревании говорит, что

    stati c factory valueOf(double) обычно является лучшим выбором, так как он, вероятно, даст значительно лучший результат. производительность в пространстве и времени.

    Хотя OpenJDK в настоящее время не кэширует упакованные двойники, стандартный метод stati c открывает путь для будущих оптимизаций. Если будет решено улучшить автобоксирование двойников либо в JVM, либо в библиотеке классов, приложения автоматически получат выгоду от оптимизации без каких-либо изменений со стороны пользователя.

  2. Другая причина в том, что Double.valueOf действительно является внутренним c методом в HotSpot. JVM знает о методах автобокса и использует эти знания при оптимизации EliminateAutoBox .

    Есть две связанные оптимизации: EliminateAllocations и EliminateAutoBox. Несмотря на то, что оба они предоставлены Escape Analysis и выглядят одинаково, они применяются в немного разных контекстах, поэтому может случиться так, что одна оптимизация работает, а другая - нет, или наоборот.

    При успешном устранении автобокса , например, когда JIT-компилятор обнаруживает совпадающие вызовы valueOf и doubleValue, и объект не ускользает, оптимизатор полностью избавляется от обоих вызовов.

    BTW, упомянутый код Whitebox не имеет значения. Он используется только для внутреннего тестирования HotSpot.

  3. Проект Valhalla , который сейчас находится в активной разработке, приводит к полному переосмыслению примитивных оберток.

    Текущая идея состоит в том, чтобы сделать int, double и т.д. c. встроенные типы с Integer и Double их ссылочными проекциями. В качестве шага миграции Integer и Double станут запечатанными абстрактными классами, поэтому не будет возможности создать их экземпляры с помощью конструкторов.

    Итак, рассматривайте отказ от конструкторов как промежуточный шаг к проекту Valhalla . Поощряя использование фабричных методов, разработчики JDK открывают путь для многих оптимизаций, которые они могут выполнять под капотом, включая встраивание Double экземпляров везде, где это возможно.

5 голосов
/ 14 июля 2020

Краткий ответ: Согласованность .

Это концепция, к которой вы должны стремиться при кодировании, потому что она снижает вероятность ошибок и делает код легче читать.

Кроме того, вы никогда не знаете, какие оптимизации могут быть добавлены в любое время , поэтому используйте метод valueOf(), если вам не требуется новое значение Double (что крайне редко ). Тот факт, что он не кэширует общие значения прямо сейчас , не означает, что этого не будет в будущем или в другой реализации.

Это концепция под названием с перспективой на будущее , к чему вы также должны стремиться при кодировании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...