简体   繁体   English

Java Double.valueOf

[英]Java Double.valueOf

At my work, all developer use Double.valueOf instead of new Double constructor.在我的工作中,所有开发人员都使用Double.valueOf而不是new Double构造函数。 In every case.在任何情况下。 For Integer or Short I can understand it for cache values but for not for double and float .对于 Integer 或 Short 我可以理解它的缓存值,但不能理解doublefloat

I look Double.valueOf in OpenJDK sources :在 OpenJDK 源代码中查看 Double.valueOf :

 /**
 * 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);
}

So it just calls Double s constructor.所以它只是调用Double的构造函数。 I can understand why the method exist for be coherent with Integer/Short...我可以理解为什么存在该方法是为了与 Integer/Short 保持一致...

But the comment on the method:但对该方法的评论:

this method should generally be used in preference to the constructor此方法通常应优先于构造函数使用

After i see its the same comment on every valueOf() method.在我看到它对每个valueOf()方法的相同评论之后。 (Integer,Short...) (整数,短...)

The comment is false?评论是假的? Or an other process meddle?还是其他进程干预?

I heard about intrinsic methods in Java, next step was search in hotspot code and in vmSymbol.hpp我听说了 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;")       

So after I grep Double.valueOf in source and I found withebox.cpp所以在我在源代码中找到 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);
}

and box method code:和盒子方法代码:

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;
}

and this code...而这段代码......

Ok, I'm not advanced yet.好吧,我还没高级。 This method box() is really called in server mode?这个方法 box() 真的是在服务器模式下调用的吗?

3 questions for resume:D简历的3个问题:D

  1. JVM intercept Double.valueOf() for call this box method? JVM 拦截Double.valueOf()以调用此框方法?

  2. Double.valueOf doesn't use JDK source and dont do a new Double() ? Double.valueOf不使用 JDK 源代码并且不执行new Double()吗?

  3. The comment on Double.valueOf() is just a dump copy/paste, Double.valueOf and new Double have same effect? Double.valueOf()的注释只是转储复制/粘贴, Double.valueOfnew Double有相同的效果吗?

  1. Integer(int) , Double(double) and similar constructors are deprecated (yes, they are actually marked as @Deprecated ) since Java 9 as a part of JEP 277 .自 Java 9 作为JEP 277的一部分以来,不推荐使用Integer(int)Double(double)和类似的构造函数(是的,它们实际上被标记为@Deprecated )。

    The deprecation comment tells that 弃用评论告诉我们

    The static factory valueOf(double) is generally a better choice, as it is likely to yield significantly better space and time performance. static 工厂valueOf(double)通常是更好的选择,因为它可能会产生明显更好的空间和时间性能。

    Although OpenJDK currently does not cache boxed doubles, static factory method opens a path for future optimizations.尽管 OpenJDK 目前不缓存盒装双精度,但 static 工厂方法为未来的优化开辟了道路。 If it is decided to improve autoboxing of doubles either in the JVM or in the class library, applications will automatically benefit from the optimization without any changes from user side.如果决定在 JVM 或 class 库中改进双打的自动装箱,应用程序将自动受益于优化,而无需从用户端进行任何更改。

  2. Another reason is that Double.valueOf is indeed an intrinsic method in HotSpot.另一个原因是Double.valueOf确实是 HotSpot 中的一个内在方法。 The JVM knows about autoboxing methods, and uses this knowledge in EliminateAutoBox optimization. JVM 了解自动装箱方法,并在EliminateAutoBox优化中使用这些知识。

    There are two related optimizations: EliminateAllocations and EliminateAutoBox.有两个相关的优化:EliminateAllocations 和 EliminateAutoBox。 Even though they are both provided by Escape Analysis and look similar, they are applied in slightly different contexts, so it may happen that one optimization works, when the other does not, or vice versa.尽管它们都由 Escape Analysis 提供并且看起来相似,但它们应用在稍微不同的上下文中,因此可能会发生一种优化有效,而另一种无效,反之亦然。

    When autoboxing elimination succeeds, eg when JIT compiler discovers matching valueOf and doubleValue calls, and the object does not escape, the optimizer gets rid of both calls altogether.当自动装箱消除成功时,例如,当 JIT 编译器发现匹配的valueOfdoubleValue调用,并且 object 没有转义时,优化器将完全摆脱这两个调用。

    BTW, the mentioned Whitebox code is irrelevant.顺便说一句,提到的白盒代码是无关紧要的。 It is not used other than for internal HotSpot testing purposes.它仅用于内部 HotSpot 测试目的。

  3. The project Valhalla , which is in active development now, leads to entire rethinking of primitive wrappers.目前正在积极开发的Valhalla项目引发了对原始包装器的全面重新思考。

    The current idea is to make int , double , etc. inline types , with Integer and Double their reference projections. 当前的想法是使用IntegerDouble作为参考投影来制作intdouble内联类型 As a migration step, Integer and Double will become sealed abstract classes, hence there will be no way to instantiate them via constructors.作为迁移步骤, IntegerDouble将成为密封的抽象类,因此无法通过构造函数实例化它们。

    So, consider deprecation of constructors as an intermediate step to the project Valhalla.因此,将弃用构造函数视为 Valhalla 项目的中间步骤。 By encouraging usage of factory methods, JDK developers clear a way for many optimizations they can do under the hood, including inlining Double instances wherever is possible.通过鼓励使用工厂方法,JDK 开发人员为他们可以在后台进行的许多优化扫清了道路,包括尽可能内联Double实例。

The short answer: Consistency .简短的回答:一致性

It is a concept you should strive for when coding, because it reduces the chance of errors, and makes the code easier to read.这是您在编码时应该努力争取的一个概念,因为它可以减少出错的机会,并使代码更易于阅读。


Besides, you never know what optimizations might be added at any time , so use the valueOf() method unless you require a new Double value (which is extremely rare).此外,您永远不知道可能随时添加哪些优化,因此请使用valueOf()方法,除非您需要新的Double值(这种情况极为罕见)。 Just because it doesn't cache common values right now , doesn't mean it won't in the future, or in a different implementation.仅仅因为它现在不缓存公共值,并不意味着它将来不会,或者在不同的实现中。

That is a concept called future-proofing , which is also something you should strive for when coding.那是一个叫做面向未来的概念,这也是你在编码时应该努力的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM