需求
需要获取一个 Method(java的函数对象) 的返回值类型是否为基本数据类型和何种基本数据类型,然后需要创建一个默认值返回。因此使用反射处理,并且 java 基本数据类型有它的包装类,所以还需要提供一个包装类和其基本数据类型的比较方法。
准备知识
1、int.class Integer.class
Integer.class 是 int.class 的包装类,如果两者直接 Integer.class == int.class 比较,返回是 false,原理是因为 Integer 的 class 内存地址和 int 的 class 内存地址不同,具体可以在 jvm 源码看到:
JVM_QUICK_ENTRY(jboolean, JVM_IsPrimitiveClass(JNIEnv *env, jclass cls))
JVMWrapper("JVM_IsPrimitiveClass");
oop mirror = JNIHandles::resolve_non_null(cls);
// 这个地方访问 class 镜像
return (jboolean) java_lang_Class::is_primitive(mirror);
JVM_END
// 通过 offset 找出这个 class 的元数据的内存地址是否为空
bool java_lang_Class::is_primitive(oop java_class) {
// should assert:
//assert(java_lang_Class::is_instance(java_class), "must be a Class object");
bool is_primitive = (java_class->metadata_field(_klass_offset) == NULL);
在 Integer.TYPE 的属性字段可以看出,TYPE 这个属性单独存放了 int.class,所以两者进行比较时候,是因为 他们的 class 内存地址不同 而返回 false:
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
getPrimitiveClass 是底层 native 方法,调用时需要 setAccessible(true) 暴力反射,因为方法访问权限是 default :
JNIEXPORT jclass JNICALL
Java_java_lang_Clas