使用jni来操作java中的数组对象。java数组分为基本类型数组和对象数组。在jni中可以使用GetArrayLength(jarray array)来获取这两组数组的长度。
1.基本类型数组
jni提供两个重要函数来处理java数组
(1) Get<Type>ArrayElements(<Type>Array arr , jboolean* isCopide);
这 类函数可以把Java基本类型的数组转换到C/C++中的数组,有两种处理方式,一种是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传 回到本地代码中,处理完本地化的数组后,通过Release<Type>ArrayElements来释放数组
(2) Release<Type>ArrayElements(<Type>Array arr , <Type>* array , jint mode)
用这个函数可以选择将如何处理Java跟C++的数组,是提交,还是撤销等,内存释放还是不释放等
mode可以取下面的值:
0 :对Java的数组进行更新并释放C/C++的数组
JNI_COMMIT :对Java的数组进行更新但是不释放C/C++的数组
JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组
在java中定义整数数组,要求在本地方法实现数组的排序,java代码为:
package com.example; public class jni_test { //在本地方法sayHello里对数组进行排序 public native void sayHello(); int []my_arr={3,7,9,1,5,2,10,6}; static{ System.loadLibrary("NativeCode"); } public static void main(String[] args) { jni_test temp=new jni_test(); temp.sayHello(); for(int i=0;i<temp.my_arr.length;i++) { System.out.println(temp.my_arr[i]); } } }
c++实现本地方法代码:
#include"com_example_jni_test.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_com_example_jni_1test_sayHello(JNIEnv * evn, jobject obj) { //获取java的Class jclass my_class=evn->GetObjectClass(obj); //获取数组属性id jfieldID arr_id=evn->GetFieldID(my_class,"my_arr","[I"); //得到数组对象 jintArray array=(jintArray)evn->GetObjectField(obj,arr_id); //把java数组转到c++数组 jint * my_array=evn->GetIntArrayElements(array,NULL); //获取数组长度 jsize size=evn->GetArrayLength(array); //利用冒泡排序进行排序 bool change;int temp; for(int i=0;i<size-1;i++) { change=false; for(int j=size-1;j>i;j--) { if(my_array[j]<my_array[j-1]) { temp=my_array[j]; my_array[j]=my_array[j-1]; my_array[j-1]=temp; change=true; } } if(!change) break; } //输出结果 /*for(int i=0;i<size;i++) cout<<my_array[i]<<endl;*/ //释放c++数组并更新java数组 evn->ReleaseIntArrayElements(array,my_array,0); }
运行结果:
2.操作自定义对象数组
自定义Person类
package com.example; public class Person { public String name; public int age; public Person() { } public Person(String name,int age) { this.name=name; this.age=age; } public void Desc() { System.out.println("姓名: "+this.name+" 年龄:"+this.age); } }
在本地方法实现Person数组按年龄排序,java代码为
package com.example; public class jni_test { //在本地方法sayHello里对数组进行排序 public native void sayHello(); Person []my_arr={new Person("小白",20),new Person("小黑",19), new Person("小红",21),new Person("小绿",18),new Person("小粉",48)}; static{ System.loadLibrary("NativeCode"); } public static void main(String[] args) { jni_test temp=new jni_test(); temp.sayHello(); } }
本地方法实现Person数组排序代码
#include"com_example_jni_test.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_com_example_jni_1test_sayHello(JNIEnv * evn, jobject obj) { //获取java的Class jclass my_class=evn->GetObjectClass(obj); //获取数组属性id jfieldID arr_id=evn->GetFieldID(my_class,"my_arr","[Lcom/example/Person;"); //得到数组对象 jobjectArray array=(jobjectArray)evn->GetObjectField(obj,arr_id); //获取数组长度 jsize size=evn->GetArrayLength(array); //cout<<size<<endl; //获取Person的数组下标为0的对象 jobject person1=evn->GetObjectArrayElement(array,0); //获取Person的class jclass person_class=evn->GetObjectClass(person1); jfieldID name_id=evn->GetFieldID(person_class,"name","Ljava/lang/String;"); jfieldID age_id=evn->GetFieldID(person_class,"age","I"); jmethodID desc_id=evn->GetMethodID(person_class,"Desc","()V"); //在本地创建一个大小和java大小一样,对象的初始化都是person1 jobjectArray jobj_arr = evn->NewObjectArray(size,person_class,person1); //把java数组的值赋给此数组 for(int i=0;i<size;i++) evn->SetObjectArrayElement(jobj_arr,i,evn->GetObjectArrayElement(array,i)); //冒泡排序--根据年龄排序 bool change=false;jobject temp; for(int i=0;i<size-1;i++) { for(int j=size-1;j>i;j--) { if(evn->GetIntField(evn->GetObjectArrayElement(jobj_arr,j),age_id)<evn->GetIntField(evn->GetObjectArrayElement(jobj_arr,j-1),age_id)) { temp=evn->GetObjectArrayElement(jobj_arr,j); evn->SetObjectArrayElement(jobj_arr,j,evn->GetObjectArrayElement(jobj_arr,j-1)); evn->SetObjectArrayElement(jobj_arr,j-1,temp); change=true; } } if(!change) break; } //调用desc函数输出结果 for(int i=0;i<size;i++) evn->CallVoidMethod(evn->GetObjectArrayElement(jobj_arr,i),desc_id); }
运行结果: