【发布时间】:2020-07-14 17:10:12
【问题描述】:
在我的工作中,所有开发人员都使用Double.valueOf 而不是new Double 构造函数。在任何情况下。对于 Integer 或 Short 我可以理解它的缓存值,但不适用于 double 和 float。
我看 Double.valueOf in OpenJDK sources :
/**
* 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);
}
所以它只是调用Doubles 构造函数。
我可以理解为什么存在该方法以与 Integer/Short 保持一致...
但是方法上的注释:
此方法一般应优先于构造函数使用
在我看到它对每个 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;")
所以在我在源代码中 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;
}
还有这段代码……
好的,我还没有进步。这个方法box()真的是在服务器模式下调用的吗?
简历的3个问题:D
-
JVM拦截
Double.valueOf()调用这个盒子方法? -
Double.valueOf不使用 JDK 源并且不使用new Double()? -
Double.valueOf()上的评论只是转储复制/粘贴,Double.valueOf和new Double效果一样吗?
【问题讨论】:
-
来自文档:“如果不需要新的 Double 实例,则通常应优先使用此方法而不是构造函数 Double(double),因为此方法可能会产生更好的效果通过缓存频繁请求的值来提高空间和时间性能" -
valueOf允许重用值。是的,还有另一个“干预”过程,即享元系统,其中相同值的对象被重用(不是所有值;通常在字节范围内),而不是构造新对象。 -
如果你好奇为什么
valueOf只是new Double,那是因为Double#valueOf有一个intrinsic method,它通常在运行时使用。但是,如果禁用此类优化,则必须有默认实现。返回new Double是默认实现。