对象深入学习,参数中有对象
直接撸代码:首先有两个实体类Person和Student
package com.example.myapplication;
import android.util.Log;
public class Student {
private static final String TAG = Student.class.getSimpleName();
public String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
Log.d(TAG, "setName: " + name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
Log.d(TAG, "setAge: " + age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.example.myapplication;
import android.util.Log;
public class Person {
private static final String TAG = Person.class.getSimpleName();
public void setStudent(Student student) {
Log.d(TAG, "setStudent: " + student.toString());
}
}
然后MainActivity中调用jni方法,没有任何参数的
jni中代码如下:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_test01(JNIEnv *env, jobject instance) {
//我想在这个函数中,直接调用Person的setStudent方法
//1,获取到全包名
const char * person_class_str = "com/example/myapplication/Person";
//2,获取到字节码对象
jclass person_class = env->FindClass(person_class_str);
//3,需要获取到jobject的对象
jobject person = env->AllocObject(person_class);
//4,调用person的setStudent方法,需要先获取methodId和签名
const char * sig = "(Lcom/example/myapplication/Student;)V";
jmethodID setStudent = env->GetMethodID(person_class,"setStudent",sig);
//5,因为setStudent的参数是Student,所以还需要创建Student的对象
const char *student_class_str = "com/example/myapplication/Student";
jclass student_class = env->FindClass(student_class_str);
jobject student = env->AllocObject(student_class);
//6,给我们创建出来的student对象赋值
sig = "(Ljava/lang/String;)V";
jmethodID setName = env->GetMethodID(student_class,"setName",sig);
jstring value = env->NewStringUTF("piter");
env->CallVoidMethod(student,setName,value);
sig = "(I)V";
jmethodID setAge = env->GetMethodID(student_class, "setAge", sig);
env->CallVoidMethod(student, setAge, 23);
//7,调用Person的setStudent方法
env->CallVoidMethod(person,setStudent,student);
//8,回收
env->DeleteLocalRef(student_class); // 遇到jclass jobject,都要记得回收
env->DeleteLocalRef(student);
env->DeleteLocalRef(person);
env->DeleteLocalRef(person_class);
}
运行结果为
image.png
全局引用和局部引用
随意来一个实体对象Dog
public class Dog {
public Dog() {
Log.d("Dog", "Dog: 构造方法被C++中直接实例化了....");
}
}
jni中代码如下:
jclass dogClass;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testDog(JNIEnv *env, jobject instance) {
// 局部引用:如果在函数里面,是在栈区,不用回收,函数结束,会自动回收
if (dogClass == NULL) { // 方法刚进来满足,执行完后虽然被释放,但是还是不等于Null
// 全局引用
const char * dog_class_str = "com/example/myapplication/Dog";
jclass temp = env->FindClass(dog_class_str);
dogClass = static_cast<jclass>(env->NewGlobalRef(temp));
}
// Java构造方法的实例化
const char * sig = "()V";
const char * method = "<init>"; // Java构造方法的标识
jmethodID init = env->GetMethodID(dogClass, method, sig);
env->NewObject(dogClass, init); // 方法执行完毕,dogClass自动释放,但是不等于null,由于dogClass 是悬空的,直接报错
//所以需要手动释放,但是手动释放完毕以后,dogClass还是不等于NULL,还需要手动改为Null
}
// 此函数就是为了 手动释放全局并且置为NULL
extern "C"
JNIEXPORT void JNICALL
Java_com_kevin_ndk09_1code_MainActivity_testUnDog(JNIEnv *env, jobject thiz) {
// TODO: implement testUnDog()
if(dogClass != NULL) {
env->DeleteGlobalRef(dogClass);
dogClass = NULL;
}
}
网友评论