【Android NDK 开发】JNI 方法解析 ( C/C++ 设置 Java 对象字段 | 查找字段 | 设置字段 )

简介: 【Android NDK 开发】JNI 方法解析 ( C/C++ 设置 Java 对象字段 | 查找字段 | 设置字段 )

文章目录

I . 设置 Java 对象 属性 流程

II . 查找 Java 对象属性 ( GetFieldID )

III . 设置 Java 对象属性 ( SetXxxField )



I . 设置 Java 对象 属性 流程


设置 Java 对象字段流程 :



① 获取属性 ID :


调用 jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) 方法 , 获取对象属性 ID ;


② 根据属性 ID 设置对象属性 :


调用 void SetIntField(jobject obj, jfieldID fieldID, jint value) 方法 , 设置对象属性 ;




II . 查找 Java 对象属性 ( GetFieldID )


1 . 函数原型 : 通过 jclass 对象 , 属性名称名称 , 和 类型签名 , 获取 Java 类对象对应的 属性 ID ;


返回值 : Java 类对象 对应的 属性 ID ( jfieldID 类型变量 )


参数 :


jclass clazz : 要获取的 Java 对象方法对应的 Java 类对象 ;
const char* name : 属性名称 ;
const char* sig : 类型签名 ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetFieldID 方法
    jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
    { return functions->GetFieldID(this, clazz, name, sig); }
    ...
}


2 . 代码示例 : 获取 Student 类的 getAge 方法 ;


student_class 是 Student 类对应的 C/C++ 中的 jclass 类型变量 ;
“age” 是 属性名称 ;
“I” 是 属性类型签名 ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
  //1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);
    //2 . 获取 Student 的 private int age 属性
    jfieldID age_field_id = env->GetFieldID(student_class, "age", "I");
  ...
}


涉及到的类型签名可以参考 : https://hanshuliang.blog.csdn.net/article/details/104108556#V__javap_____141




III . 设置 Java 对象属性 ( SetXxxField )


1 . 函数原型 : 通过 Java 对象 , 属性 ID , 和 Java 数据类型属性参数 , 设置对应的 Java 对象属性 ;


返回值 : void


参数 :


jobject obj : 要设置属性的 Java 对象 ;
jfieldID fieldID : 属性 ID ;
jint value : Java 的 int 类型属性值 ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 SetIntField 方法
    void SetIntField(jobject obj, jfieldID fieldID, jint value)
    { functions->SetIntField(this, obj, fieldID, value); }
    ...
}



2 . 设置方法汇总 :



设置 int 类型属性 , 调用 void SetIntField(jobject obj, jfieldID fieldID, jint value) 方法 ;

设置 boolean 类型属性 , 调用 void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value) 方法 ;


下面是设置 8 种基本数据类型 和 引用类型 , 共 9 中类型应该调用的方法 ;



注意 : 所有设置的类型 , 都是 Java 数据类型 , 如 jobject , jint , jboolean 类型 ;



struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 SetXxxField 方法
    void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
    { functions->SetObjectField(this, obj, fieldID, value); }
    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value)
    { functions->SetBooleanField(this, obj, fieldID, value); }
    void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
    { functions->SetByteField(this, obj, fieldID, value); }
    void SetCharField(jobject obj, jfieldID fieldID, jchar value)
    { functions->SetCharField(this, obj, fieldID, value); }
    void SetShortField(jobject obj, jfieldID fieldID, jshort value)
    { functions->SetShortField(this, obj, fieldID, value); }
    void SetIntField(jobject obj, jfieldID fieldID, jint value)
    { functions->SetIntField(this, obj, fieldID, value); }
    void SetLongField(jobject obj, jfieldID fieldID, jlong value)
    { functions->SetLongField(this, obj, fieldID, value); }
    void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
    { functions->SetFloatField(this, obj, fieldID, value); }
    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)
    { functions->SetDoubleField(this, obj, fieldID, value); }
  //设置静态属性
    jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
    { return functions->GetStaticMethodID(this, clazz, name, sig); }
    ...
}


3 . 代码示例 : 获取 Student 类的 getAge 方法 ;


student 是 Student 类对应的 C/C++ 中的 Java 对象 ;
age_field_id 是 属性 ID ;
90 是 属性值 , jint 类型 ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
  //1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);
    //2 . 获取 Student 的 private int age 属性
    jfieldID age_field_id = env->GetFieldID(student_class, "age", "I");
  //3 . 设置 Student 的 age 属性值 90
  env->SetIntField(student, age_field_id, 90);
  ...
}


目录
相关文章
|
5天前
|
安全 前端开发 Java
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
19 3
|
6天前
|
供应链 Java API
Java 8新特性解析及应用区块链技术在供应链管理中的应用与挑战
【4月更文挑战第30天】本文将深入探讨Java 8的新特性,包括Lambda表达式、Stream API和Optional类等。通过对这些新特性的详细解析和应用实例,帮助读者更好地理解和掌握Java 8的新技术。
|
7天前
|
安全 Java API
Java 8新特性深度解析
【4月更文挑战第30天】本文将深入探讨Java 8的新特性,包括Lambda表达式、Stream API、Optional类等,以及这些新特性如何改变我们编写Java代码的方式。
|
7天前
|
算法 Java
【Java探索之旅】运算符解析 算术运算符,关系运算符
【Java探索之旅】运算符解析 算术运算符,关系运算符
15 0
|
8天前
|
存储 Java 大数据
JAVA:编程的艺术与实战解析
JAVA:编程的艺术与实战解析
17 2
|
9天前
|
设计模式 Java
Java 设计模式:工厂模式与抽象工厂模式的解析与应用
【4月更文挑战第27天】设计模式是软件开发中用于解决常见问题的典型解决方案。在 Java 中,工厂模式和抽象工厂模式是创建型模式中非常核心的模式,它们主要用于对象的创建,有助于增加程序的灵活性和扩展性。本博客将详细介绍这两种模式的概念、区别以及如何在实际项目中应用这些模式。
14 1
|
10天前
|
并行计算 Java API
【专栏】Java中的Lambda表达式应用与实例解析
【4月更文挑战第27天】Java 8的Lambda表达式增强了函数式编程,允许以匿名函数形式传递行为。其基本语法`(params) -> expression/statements`,类型由参数推断,可引用final或effectively final的外部变量。Lambda广泛应用于集合操作(如Stream API)、并行流处理和GUI事件处理,简化代码并提高效率。通过实例,展示了Lambda在集合筛选、并行计算和事件处理中的应用,从而提高开发质量和效率。
|
11天前
|
XML Java 开发工具
阿里云大学考试Java高级题目及解析-java高级
阿里云大学考试Java高级题目及解析-java高级
|
11天前
|
SQL Java 开发工具
阿里云大学考试Java中级题目及解析-java中级
阿里云大学考试Java中级题目及解析-java中级
|
11天前
|
Java 开发工具 数据库
阿里云大学考试Java初级题目及解析-java初级
阿里云大学考试Java初级题目及解析-java初级