关于 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 的说明的主要内容,如果未能解决你的问题,请参考以下文章

Android GetMethodID 函数的说明

Class.getFields() 返回的字段顺序

Java反射 getFields和getDeclaredFields的区别

避免 getfield 操作码

反射之getField()与getDeclaredField()的区别

getField()与getDeclaredField()的区别