以优雅直观的方式调用JAVA对象方法和读写JAVA对象成员
在 JNI (Java Native Interface, http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html) 中,涉及调用JAVA对象方法的函数主要有:
jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
以上函数,除了 GetMethodID() 之外,同属于一个系列:CallXXXMethod(),它们的参数是相同的,只是返回值和函数名称不同。CallXXXMethod() 系列函数用于调用对象的实例方法(Instance Methods),还有另外两个系列函数 CallStaticXXXMethod(), CallNonvirtualXXXMethod(),分别用于调用静态方法(Static Methods)和非虚拟方法(Nonvirtual Methods)。在以上三个系列中的任一函数,又都有三种变形,主要是接收的参数不同:
XXX CallXXXMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
XXX CallXXXMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
XXX CallXXXMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args);
这样算下来,JNI中仅用于调用JAVA方法的函数就多达 10 * 3 * 3 = 90 个(未计算 GetMethodID(), GetStaticMethodID(), GetNonvirtualMethodID())。想想都有些眼晕了~!@#$%^&*()。没办法,在C语言中,一个函数只能有一个确定的返回值类型,参数也无法重载。(从应用程序开发者的角度出发,并无所谓函数的多少,需要哪个就调用哪个嘛;从类库开发者的角度出发,还是希望提供最简洁的接口,以方便应用程序开发者。)
可是在“易语言.飞扬”(http://blog.csdn.net/efdev/)中,用于调用JAVA方法的函数(方法)仅仅只有 3 个:
通用型 JObject.调用方法(JMethod 欲调用的方法, 通用型 参数 <扩展开始>, ...)
通用型 JObject.调用非虚方法(JClass 欲调用方法所属类, JMethod 欲调用的方法, 通用型 参数 <扩展开始>, ...)
通用型 JClass.调用静态方法(JMethod 欲调用的方法, 通用型 参数 <扩展开始>, ...)
因为“通用型”数据类型的存在,不需要再针对每一个类型的返回值分别使用单独的方法,这是最主要的简化之处。另外,JNIEnv*, jobject, jclass, jmethodID 等已经不复存在,被分别封装成了EF对象,进一步简化之,并且OO化了。
在 JNI 中,涉及读写JAVA成员的函数主要有:
jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
XXX GetXXXField(JNIEnv *env, jobject obj, jfieldID fieldID);
void SetXXXField(JNIEnv *env, jobject obj, jfieldID fieldID, XXX value);
jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
XXX GetStaticXXXField(JNIEnv *env, jclass clazz, jfieldID fieldID);
void SetStaticXXXField(JNIEnv *env, jclass clazz, jfieldID fieldID, XXX value);
算下来,JNI中仅用于读写类/对象成员的函数就多达 10 * 4 = 40 个(未计算 GetFieldID(), GetStaticFieldID)。看起来也够眼晕的。
可是在“易语言.飞扬”(EF)中,用于读写JAVA类/对象成员的函数(方法)只有 4 个:
通用型 JObject.取成员值(JField 欲取其值的成员);
逻辑 JObject.置成员值(JField 欲置其值的成员, 通用型 值);
通用型 JClass.取静态成员值(JField 欲取其值的成员);
逻辑 JClass.置静态成员值(JField 欲置其值的成员, 通用型 值);
总结:1、大大减少了函数(方法)数量;2、对接口进行了面向对象(OO)化设计。