在我的工作中,所有开发人员都使用Double.valueOf而不是new Double构造函数。在每种情况下。对于 Integer 或 Short 我可以理解它的缓存值但不是 fordouble和float。
我在 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);
}
Run Code Online (Sandbox Code Playgroud)
所以它只是调用Doubles 构造函数。我可以理解为什么存在与整数/短一致的方法...
但对该方法的评论:
这种方法通常应该优先于构造函数使用
在我看到它对每种valueOf()方法的相同评论之后。(整数,短...)
评论是假的?还是其他进程干预?
我听说过 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;")
Run Code Online (Sandbox Code Playgroud)
所以在我Double.valueOf在源代码中grep 之后,我找到了withebox.cpp
static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}
Run Code Online (Sandbox Code Playgroud)
和框方法代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
而这段代码...
好吧,我还没进阶。这个方法 box() 真的是在服务器模式下调用的吗?
简历的 3 个问题 :D
JVM拦截Double.valueOf()调用此框方法?
Double.valueOf不使用 JDK 源代码并且不执行new Double()?
评论Double.valueOf()只是转储复制/粘贴,Double.valueOf并new Double具有相同的效果?
apa*_*gin 11
Integer(int),Double(double)并且类似的构造函数已被弃用(是的,它们实际上被标记为@Deprecated),因为 Java 9 作为JEP 277的一部分。
该弃用评论告诉
静态工厂
valueOf(double)通常是更好的选择,因为它可能会产生明显更好的空间和时间性能。
尽管 OpenJDK 目前不缓存盒装双精度,静态工厂方法为未来的优化开辟了道路。如果决定在 JVM 或类库中改进双精度自动装箱,应用程序将自动从优化中受益,而无需用户端进行任何更改。
另一个原因是这Double.valueOf确实是 HotSpot 中的一个内在方法。JVM知道自动装箱方法,并在EliminateAutoBox优化中使用这些知识。
有两个相关的优化:EliminateAllocations 和 EliminateAutoBox。尽管它们都由 Escape Analysis 提供并且看起来相似,但它们应用在略有不同的上下文中,因此可能会发生一种优化有效而另一种无效的情况,反之亦然。
当自动装箱消除成功时,例如,当 JIT 编译器发现匹配valueOf并doubleValue调用时,并且对象没有转义,优化器会完全消除这两个调用。
顺便说一句,提到的白盒代码是无关紧要的。除了用于内部 HotSpot 测试目的之外,它不会被使用。
现在正在积极开发的Valhalla项目导致了对原始包装器的全面重新思考。
在目前的想法是让int,double等直列类型,与Integer和Double其基准凸。作为迁移步骤,Integer并且Double将成为密封的抽象类,因此将无法通过构造函数实例化它们。
因此,将弃用构造函数视为 Valhalla 项目的中间步骤。通过鼓励使用工厂方法,JDK 开发人员为他们可以在幕后进行的许多优化扫清了道路,包括Double尽可能内联实例。
| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |