本节讲的是在 C/C++本地代码中创建Java对象,JNI 中提供两个方法进行Java对象的操作,分别是 NewObject 和 Allocobject,先看下jni.h 头文件中对两个方法的定义
jobject NewObject(jclass clazz, jmethodID methodID, ...) { va_list args; jobject result; va_start(args, methodID); result = functions->NewObjectV(this,clazz,methodID,args); va_end(args); return result; }
jobject AllocObject(jclass clazz) { return functions->AllocObject(this,clazz); }
GetMethodID 能够获取构造方法的jmethod,如果传入的要取得的方法名称设定为”<init>”就能取得构造方法构造方法没有返回值,签名始终为Void (()V)
下面是一个通过C++创建Java的Date对象并在Java控制台输出1970到现在毫秒数
package com.fomagic; public class TestNative { public native void sayHello(); // C++本地代码实现 public static void main(String[] args) { System.loadLibrary("NativeCode");// 加载动态链接库,不能加 .dll TestNative test = new TestNative(); test.sayHello(); } }
C++
JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *env, jobject obj) { jclass clazz_date = env->FindClass("java/util/Date"); //找到Date类 jmethodID id_date= env->GetMethodID(clazz_date,"<init>","()V"); //通过类获取构造方法ID,默认无返回值 jobject now=env->NewObject(clazz_date,id_date); //创建Date的实例对象 jmethodID id_date_getTime=env->GetMethodID(clazz_date,"getTime","()J"); //获取Date类的getTime()方法的ID,返回值是long 即 JNI中对应的 J jlong time = env->CallLongMethod(now,id_date_getTime); //通过now对象调用getTime()方法,得到时间 cout<<time<<endl; }
代码很简单通过前面的知识都是可以明白的,注释应该没什么问题(吧)
使用函数AllocObject 可以根据传入的jclass创建一个Java对象
但他的状态是非初始化的,在使用这个对象之前绝对要用CallNovirtualVoidMethod
来调用该jclass的建构函数,这样可以延迟构造函数的调用,这一部分用的很少
(对于这个函数到底是什么意思,我也没有完全搞明白,只是知道这样用,以后慢慢研究)
jclass clazz_str =env->FindClass("java/lang/String"); jmethodID methodID_str=env->GetMethodID(clazz_str,"<init>","([C)V");//获取构造方法ID jObject string =env->AllocObject(clazz_str);// 预先创建没有初始化的字符串 jcharArray arg=env->NewCharArray(4); //创建长度为4的字符数组 env->SetCharArrayRegion(arg,0,4,L"奇幻未来"); //复制"奇幻未来"到数组arg中 env->CallNonvirtualVoidMethod(string,clazz_str,methodID_str,arg); //讲arg字符数组复制给string jclass clazz_this=env->GetObjectClass(obj); // 这是视频中假设这个对象的类中有定义 static String STATIC_STR; jfieldID fieldID_str=env->GetStaticFieldID(clazz_this,"STATIC_STR","Ljava/lang/String;"); env->SetStaticObjectField(clazz_str,fieldID_str,string);