jni调用java父类方法,在知道这个之后,我感觉jni能做的事真是厉害。我们一起来看看它与java的不同
一. jni调用java父类方法
先做个准备:
- 准备一个Java父类和子类,People和Beibi:
public class People {
private static final String TAG = People.class.getSimpleName();
/**
* 说方法,在其中调用下sayAge
*/
public void say() {
Log.d(TAG, "people say");
sayAge();
}
public void sayAge() {
Log.d(TAG, "people say age");
}
}
public class Beibi extends People {
private static final String TAG = Beibi.class.getSimpleName();
private int age;
private String name;
public Beibi(int age, String name) {
this.age = age;
this.name = name;
}
/**
* 重写的父类说方法
*/
@Override
public void say() {
Log.d(TAG, "beibi say:my name is " + name);
}
/**
* 重写的父类说方法
*/
@Override
public void sayAge() {
Log.d(TAG, "beibi say:my age is " + age);
}
}
- 先来java方法来调用下say
/*使用java来创建进行调用say方法*/
People beibi = new Beibi(12, "小北鼻");
beibi.say();
- 输出
beibi say:my name is 小北鼻
这是我们正常情况下的多态的情况,不用说明了,至少我的理解是,正常使用情况下,只要实例是Beibi,在外部调用say方法,怎么调用都是Beibi的say,是调用不到People的say的。
接下来我们看jni,步骤:
- 创建Beibi的实例,并调用Beibi的say方法
- 依旧使用北鼻的实例,再调用People的say方法:使用CallNonvirtualVoidMethod
直接上代码,代码中有注释:
//1. 找Beibi的class
jclass class_beibi = env->FindClass("shixin/ndkdemo/supermethod/Beibi");
if (class_beibi == NULL) {
LOGE("beibi class 寻找失败");
return 1;
}
//2. 找Beibi的构造方法id,参数是int,String
jmethodID jmethodID_init = env->GetMethodID(class_beibi, "<init>",
"(ILjava/lang/String;)V");
if (jmethodID_init == NULL) {
LOGE("beibi 构造方法 寻找失败");
return 1;
}
//3. 创建Beibi对象
jobject obj_beibi = env->NewObject(class_beibi, jmethodID_init, age_, name_);
if (obj_beibi == NULL) {
LOGE("beibi 对象创建失败");
return 1;
}
//4. 调用Beibi的say方法
jmethodID jmethodID1_say = env->GetMethodID(class_beibi, "say", "()V");
if (jmethodID1_say == NULL) {
LOGE("beibi say方法寻找失败");
return 1;
}
env->CallVoidMethod(obj_beibi, jmethodID1_say);
/*···········下面来调用父类方法··········*/
//5. 找到父类,People的class
jclass class_people = env->FindClass("shixin/ndkdemo/supermethod/People");
if (class_people == NULL) {
LOGE("People class 寻找失败");
return 1;
}
//6. 找到People的say方法id
jmethodID jmethodID1_people_say = env->GetMethodID(class_people, "say", "()V");
if (jmethodID1_people_say == NULL) {
LOGE("people say方法 寻找失败");
return 1;
}
//7. 调用父类方法 使用 CallNonvirtualVoidMethod 方法,参数:实例对象,class,方法id
env->CallNonvirtualVoidMethod(obj_beibi, class_people, jmethodID1_people_say);
- 输出:
D/Beibi: beibi say:my name is 大北鼻
D/People: people say
D/Beibi: beibi say:my age is 13
在输出就能看到:
- 咱们第一步调用Beibi实例的say方法正常调用
- 使用Beibi实例来调用父类People的方法,say真的是执行的父类的方法,然后在say中调用的sayAge又因为子类的重写调用的Beibi的sayAge
二. 总结
- 使用CallNonvirtualXXMethod可以调用传入实例obj与父类的class和methodid来调用父类的XX返回类型的方法
- 第一步仅在指定这个class和methodid的方法有效,对于实例方法中调用的被子类复写的方法依旧会调用到子类的方法