JNI 中Java对象操作:
对象操作相关函数: (AllocObject,NewObject,NewObjectA,NewObjectV,GetObjectRefType,IsInstanceOf,IsSameObject)
*
Athor: 左少华
Blog: http://blog.csdn.net/shaohuazuo/article/details/43309625
*
1.对比函数特性.
1.1 AllocObject 函数和NewObject,NewObjectA,NewObjectV,之间的区别, 共同点
不同点: AllocObject不需要调用如何构造函数产生一个Java对象.而NewObject,NewObjectA,NewObjectV,
是通过调用Java类的构造函数生成对象的.
相同点: AllocObject和NewObject,NewObjectA,NewObjectV,他们的jclass对象都不能是数组类型的引用.
1.2 NewObject,NewObjectA,NewObjectV,之间的区别和共同点.
不同点: 他们传递给构造函数的参数传递形式不一样.一个是可以参数 (...)形式的.一个是(jvalue *args)数组类型的.
第三个是一个va_list结构体类型的变参数,来传递构造函数的参数.
相同点: 调用这三个函数都必须要先得到构造函数的MethodID,然后使用构造函数进行初始化.
1.3 GetObjectRefType函数,用来得到一个对象引用类型.(JNI1.6新特性)
GetObjectRefType一共能获取四种不同类型引用值.他是JNI标准中定义了上面四种类型的引用的枚举值
JNIInvalidRefType = 0, JNILocalRefType = 1, JNIGlobalRefType = 2, JNIWeakGlobalRefType = 3
JNIInvalidRefType:无效的引用类型,GetObjectRefType(env,NULL)方法返回的就是JNIInvalidRefType
JNILocalRefType:如果该方法第二参数对象是一个Local对象的引用.那么返回值就是.JNILocalRefType,通常第二对象也可以通过NewLocalRef()生成.JNIGlobalRefType:如果该方法第二个参数是一个Global对象,那么返回值就是.JNIGlobalRefType,通常第二参数可以通过NewGlobalRef()生成.
JNIWeakGlobalRefType : 如果第二个参数是一个WeakGlobal对象.那么这个方法的返回只就是JNIWeakGlobalRefType,
同通常第二参数可以通过NewGlobalRef()生成.
1.4IsInstanceOf方法.
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。
instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例
isInstanceOf方法和java中的instanceof方法是一样的.
java中instanceof的用法如下:instanceof方法主要是再类型强制的时候,会先做这个判断,如何再进行强制类型转换.
public class A{
private A a = new A();
public static void main(String[] args){
if( a instanceof A){
system.out.println("a对象是A类型的实例");
}
}
}
接下来我们讲再C中介绍他的用法.
1.5IsSameObject方法.
这个方法测试的是两个引用是否是引用的同一个java对象.
1.AllocObject
1.1 函数原型
jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj);
1.2 函数参数
env: the JNI interface pointer. (是一个JNI接口指针.)clazz: a Java class object. (一个java的class对象.
1.3 返回值
RETURNS:
Returns a Java object, or NULL if the object cannot be constructed.
成功返回Java对象.不成功返回NULL.
1.4 异常
THROWS:可能出现一下两种异常.
InstantiationException: if the class is an interface or an abstract class. 这个class是一个抽象类,或者是一个接口.
OutOfMemoryError: if the system runs out of memory. 系统内存不够
1.5 demo:
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_MainActivity_AllocObjectDemo(JNIEnv *pEnv, jobject pObj) {
jclass testCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Test"); //通过类名获取Test的类对象。
jobject allocObj = (*pEnv)->AllocObject(pEnv, testCls); //通过类对象获取Java对象。
return allocObj; //并返回到Java层。
}
2. NewObject
2.1函数原型
jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2.2函数参数
env: the JNI interface pointer. (是JNI接口指针.)
clazz: a Java class object. 一个java 类对象.
methodID: the method ID of the constructor. 它是java类的构造方法的ID,可以通过GetMethodID获取
...:是构造函数的参数.
2.3函数返回值
返回这个类的java对象。
2.4异常
2.5demo
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_MainActivity_NewObjectDemo
(JNIEnv *pEnv, jobject pObj, jstring pName, jint pAge) {
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person"); //获取Person的Class对象。
jmethodID method = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","(Ljava/lang/String;I)V"); //获取构造函数的Id.
jobject newObj = (*pEnv)->NewObject(pEnv, personCls, method, pName, pAge); //使用NewObject方法通过调用构造函数,生成Java对象。
return newObj; //返回该对象到Java层。
}
3.NewObjectA
3.1函数原型
jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
3.2函数参数
env: the JNI interface pointer. (是JNI接口指针.)
clazz: a Java class object. 一个java 类对象.
methodID: the method ID of the constructor. 它是java类的构造方法的ID,可以通过GetMethodID获取
args:是构造函数的参数.
3.3函数返回值
返回这个类的java对象。
3.4异常
3.5demo
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_MainActivity_NewObjectADemo
(JNIEnv *pEnv, jobject pObj, jstring pName, jint pAge) {
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person");//获取Person的Class对象。
jmethodID method = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","(Ljava/lang/String;I)V"); //获取构造函数的Id.
jvalue args[2]; //构造一个jvalue结构体类型的参数数组。
args[0].l = pName;
args[1].i = pAge;
jobject newObjA = (*pEnv)->NewObjectA(pEnv, personCls, method, args); //使用NewObject方法通过调用构造函数,生成Java对象。
return newObjA;
}
4.NewObjectV
4.1函数原型
jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
4.2函数参数
env: the JNI interface pointer. (是JNI接口指针.)
clazz: a Java class object. 一个java 类对象.
methodID: the method ID of the constructor. 它是java类的构造方法的ID,可以通过GetMethodID获取
va_list:是构造函数的参数.
4.3函数返回值
返回这个类的java对象。
4.4异常
4.5demo
static jobject newObjectVUtil(JNIEnv *pEnv, ...) {
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person");
jmethodID method = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","(Ljava/lang/String;I)V");
va_list arList;
va_start(arList, pEnv);
jobject newObjV = (*pEnv)->NewObjectV(pEnv, persontCls, method, arList);
va_end(arList);
return newObjV;
}
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_MainActivity_NewObjectVDemo
(JNIEnv *pEnv, jobject pObj, jstring pName, jint pAge) {
return newObjectVUtil(pEnv, pName, pAge);
}
5.GetObjectRefType
5.1函数原型 1.6版本的新特性
jobjectRefType (JNICALL *GetObjectRefType) (JNIEnv* env, jobject obj);
5.2函数参数
env: the JNI interface pointer. (是JNI接口指针.)
obj: a local, global or weak global reference. 一个局部,或则是全局或者是(全局的弱)对象引用。
5.3函数返回值
函数的返回值他是一个,枚举类型。表示枚举的的只由四个。
JNIInvalidRefType = 0,JNILocalRefType = 1,JNIGlobalRefType = 2, JNIWeakGlobalRefType = 3
GetObjectRefType(env,NULL)得到只就是。JNIInvalidRefType的值。其他得到就是相关枚举类型的值。
5.4异常
5.5demo
jobjcet obj;
JNIEXPORT jobject JNICALL Java_com_zuoshaohua_MainActivity_GetObjectRefTypeDemo{
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person");
jclass personSubCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/PersonSub");
jmethodID personConstrucat = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","()V");
jmethodID personSubConstructor = (*pEnv)->GetMethodID(pEnv, personSubCls, "<init>","()V");
jobject personObj = (*pEnv)->NewObject(pEnv, personCls, personConstructor);
jobject personSubObj = (*pEnv)->NewObject(pEnv, personSubCls, personSubConstructor);
obj = (*pEvn)->NewGlobalRef(pEnv,personSubObj);
__android_log_print(ANDROID_LOG_INFO, "GetObjectRefTypeDemo", "personSubObj is: %d",
(*pEnv)->GetObjectRefType(pEnv, personSubObj));
__android_log_print(ANDROID_LOG_INFO, "GetObjectRefTypeDemo", "obj is: %d",
(*pEnv)->GetObjectRefType(pEnv, obj));
.....
}
6.IsInstanceOf
6.1函数原型
jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz);
6.2函数参数
env: the JNI interface pointer. JNI接口指针。
obj: a Java object. java的对象,和java中的instanceof是一个功能。
clazz: a Java class object. 一个类对象。
6.3函数返回值
如果Java obj是clazz的对象。那么返回JNI_TRUE,否则返回JNI_FALSE.
JNI_TRUE
JNI_FALSE
6.4异常
6.5demo
在Java中由一个Person类如下。
public class Person{}
PersonSub继承了,PersonSub类,如下。
public class PersonSub extends Person{}
下面使用IsInstanceOf判断对象是不是类的实例,他和java层的instanceof是一样的。
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person");
jclass personSubCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/PersonSub");
jmethodID personConstrucat = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","()V");
jmethodID personSubConstructor = (*pEnv)->GetMethodID(pEnv, personSubCls, "<init>","()V");
jobject personObj = (*pEnv)->NewObject(pEnv, personCls, personConstructor);
jobject personSubObj = (*pEnv)->NewObject(pEnv, personSubCls, personSubConstructor);
__android_log_print(ANDROID_LOG_INFO, "IsInstanceOfDemo", "personObj, perosnCls: %d", (*pEnv)->IsInstanceOf(pEnv, personObj, personCls));
__android_log_print(ANDROID_LOG_INFO, "IsInstanceOfDemo", "personObj, personSubCls: %d", (*pEnv)->IsInstanceOf(pEnv, personObj, personSubCls));
__android_log_print(ANDROID_LOG_INFO, "IsInstanceOfDemo", "personSubObj, personCls: %d", (*pEnv)->IsInstanceOf(pEnv, personSubObj, personCls));
__android_log_print(ANDROID_LOG_INFO, "IsInstanceOfDemo", "personSubObj, personSubCls: %d", (*pEnv)->IsInstanceOf(pEnv, personSubObj, personSubCls));
7.IsSameObject
7.1函数原型
jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2);
7.2函数参数
env: the JNI interface pointer.
ref1: a Java object.
ref2: a Java object.
7.3函数返回值
如果ref1,和ref2引用的是同一个对象。那么返回只为真。否则返回值为假。
JNI_TRUE
JNI_FALSE
7.4异常
7.5demo
jclass personCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/Person");
jclass personSubCls = (*pEnv)->FindClass(pEnv, "com/zuoshaohua/PersonSub");
jmethodID personConstrucat = (*pEnv)->GetMethodID(pEnv, personCls, "<init>","()V");
jmethodID personSubConstructor = (*pEnv)->GetMethodID(pEnv, personSubCls, "<init>","()V");
jobject personObj = (*pEnv)->NewObject(pEnv, personCls, personConstructor);
jobject personSubObj = (*pEnv)->NewObject(pEnv, personSubCls, personSubConstructor);
__android_log_print(ANDROID_LOG_INFO, "IsInstanceOfDemo", "personObj, personSubObj: %d",
(*pEnv)->IsSameObject(pEnv, personObj,personSubObj));