关于 GetFieldID 的说明
Posted
技术标签:
【中文标题】关于 GetFieldID 的说明【英文标题】:Clarification about GetFieldID 【发布时间】:2016-10-03 01:21:15 【问题描述】:我试图构建一个本地方法,虽然它似乎运行良好,但我很难理解函数中的字段 [*sig] -
jfieldID GetFieldID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
例如,我有一个小的 Java 代码,它使用了一个名为“i”的实例变量,而这个本地方法(命名为 test)所做的就是将这个乘以 2。
现在我指的是 Java Complete Reference book - 这里的代码是这样的 -
我的问题是——这里面的“我”是什么—— fid = (*env)->GetFieldId(env,cls,"i", "I");
当我阅读 Oracle 文档时,它说 - https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
访问对象的字段 获取字段ID
jfieldID GetFieldID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
返回类的实例(非静态)字段的字段 ID。该字段由其名称和签名指定。访问器函数的 GetField 和 SetField 系列使用字段 ID 来检索对象字段。 GetFieldID() 会导致一个未初始化的类被初始化。 GetFieldID() 不能用于获取数组的长度字段。请改用 GetArrayLength()。 链接: JNIEnv接口函数表中的索引94。 参数: env:JNI 接口指针。 clazz:Java 类对象。 name:以 0 结尾的修改后的 UTF-8 字符串中的字段名称。 sig:以 0 结尾的修改后的 UTF-8 字符串中的字段签名。
您能否详细说明一下这个字段“sig”是什么?我无法将“我”与任何事物联系起来。
#include <jni.h>
#include "NativeDemo.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_NativeDemo_test(JNIEnv *env , jobject obj)
jclass cls;
jfieldID fid;
jint i;
printf("Starting the native method\n");
cls = (*env)->GetObjectClass(env,obj);
fid = (*env)->GetFieldId(env,cls,"i", "I");
【问题讨论】:
这种性质的 JNI 方法或字段签名是javap -s
命令为该方法或字段输出的内容。当有一种工具可以为您解决这些问题时,不要费心自己去弄清楚它们。
【参考方案1】:
这里的“I”是原始整数类型的签名。 Oracle 提供了类型签名表:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp276
Z 布尔值 B 字节 C 字符 S 短 我理解 J 长 F 浮动 D双对于非原始类型,签名的格式为
L 完全合格的类;对于数组,添加 [。
对于方法,() 用于分隔参数和返回值。
【讨论】:
谢谢。这回答了我的问题。【参考方案2】:请参阅下面的 Core Java, v. 2 ch 中的“员工”示例。 12,霍斯特曼和康奈尔在http://www.horstmann.com/corejava.html “id”是字段的名称,这里 私人双薪; 在 Employee 类中;还必须指定其签名(“sig”)或类型“D”(双精度)。在您的代码中,“I”是整数。 请参阅http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html 的“类型字段” 一旦得到jFieldId,就可以用来修改 字段。
/**
@version 1.10 1999-11-13
@author Cay Horstmann
*/
#include "Employee.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_Employee_raiseSalary(JNIEnv* env, jobject this_obj, jdouble byPercent)
/* get the class */
jclass class_Employee = (*env)->GetObjectClass(env, this_obj);
/* get the field ID */
jfieldID id_salary = (*env)->GetFieldID(env, class_Employee, "salary", "D");
/* get the field value */
jdouble salary = (*env)->GetDoubleField(env, this_obj, id_salary);
salary *= 1 + byPercent / 100;
/* set the field value */
(*env)->SetDoubleField(env, this_obj, id_salary, salary);
【讨论】:
谢谢。这回答了我的问题。以上是关于关于 GetFieldID 的说明的主要内容,如果未能解决你的问题,请参考以下文章
Java反射 getFields和getDeclaredFields的区别