★06.访问属性

实例属性 与 静态属性

  • 实例属性:同一个类每一个对象都会拥有一份的属性。
  • 静态属性:同一个类的所有对象都共享的属性。

实例属性

简单示例

public class InstanceFieldAccess {
    static {
        System.loadLibrary("InstanceFieldAccess");
    }

    public static void main(String[] args) {
        InstanceFieldAccess c = new InstanceFieldAccess();
        c.s = "abc";
        c.accessField();
        System.out.println("In Java:");
        System.out.println("c.s = \"" + c.s + "\"");
    }

    private native void accessField();

    private String s;
}
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv * env, jobject obj) {
    // 使用jobject来获取其对应的jclass
    jclass cls = (* env)->GetObjectClass(env, obj);

    // 使用jclass、属性名、属性描述符来获取类中的属性ID
    jfieldID fid = (* env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
    if (!fid) {
        return;
    }

    // 使用属性ID和jobject来获取属性值
    jstring jstr = (* env)->GetObjectField(env, obj, fid);

    // 使用获取的属性值
    const char * str = (* env)->GetStringUTFChars(env, jstr, NULL);
    if (!str) {
        return;
    }
    printf("In C: \n");
    printf("c.s = \"%s\"\n", str);
    (* env)->ReleaseStringUTFChars(env, jstr, str);

    // 创建新的属性值
    jstring newJstr = (* env)->NewStringUTF(env, "123");
    if (!newJstr) {
        return;
    }

    // 将新的属性值赋值给属性
    (* env)->SetObjectField(env, obj, fid, newJstr);
}

示例解说

  • 属性描述符 :描述属性类型的j符串。简单例子如下:
    • 使用"F"表示float
    • 使用"D"表示double
    • 使用"Z"表示boolean
    • 使用"[I"表示int[]
    • 使用"Ljava/lang/String;"表示java.lang.String
  • 创建查看 属性描述符 的便捷工具,可以避免手写 属性描述符
    1. File -> Settings -> External Tools。
    2. 点击 “+” 按钮。
      1. Name : 输出类描述符
      2. Group : JNI
      3. Options : 全部勾选。
      4. Show in : 全部勾选。
      5. Program : $JDKPath$\bin\javap.exe
      6. Parameters : -s -p $FileClass$-p选项用于输出私有成员。
      7. Working directory : $OutputPath$
    3. 点击确定。
  • 示例步骤:
    1. 使用jobject获取其对应的jclass
    2. 使用jclass属性名属性描述符 来获取属性的jfieldID
    3. 使用jfieldIDjobject来获取属性值。
    4. 使用jobjectjfieldID新属性值 来给属性赋值。

函数解说

  • GetObjectClass():用于获取jobject对应的jclass
  • GetFieldID():用于获取 实例属性 IDjfieldID
  • GetField():用于获取jobject中的属性。
  • SetField():用于给jobject中的属性赋值。

静态属性

简单示例

public class StaticFieldAccess {
    static {
        System.loadLibrary("StaticFieldAccess");
    }

    public static void main(String args[]) {
        StaticFieldAccess c = new StaticFieldAccess();
        StaticFieldAccess.si = 100;
        c.accessField();
        System.out.println("In Java:");
        System.out.println("StaticFieldAccess.si = " + si);
    }

    private native void accessField();

    private static int si;
}
JNIEXPORT void JNICALL Java_StaticFieldAccess_accessField(JNIEnv * env, jobject obj) {
    // 使用jobject来获取其对应的jclass
    jclass cls = (* env)->GetObjectClass(env, obj);

    // 使用jclass、属性名、属性描述符来获取类中的属性ID
    jfieldID fid = (* env)->GetStaticFieldID(env, cls, "si", "I");
    if (!fid) {
        return;
    }

    // 使用属性ID和jclass来获取属性值
    jint si = (* env)->GetStaticIntField(env, cls, fid);

    // 使用获取的属性值
    printf("In C:\n");
    printf("StaticFieldAccess.si = %li\n", si);

    // 给属性设置新属性值
    (* env)->SetStaticIntField(env, cls, fid, 200);
}

示例解说

  • 示例步骤:
    1. 使用jobject获取其对应的jclass
    2. 使用jclass属性名属性描述符 来获取属性的jfieldID
    3. 使用jfieldIDjclass来获取属性值。
    4. 使用jclassjfieldID新属性值 来给属性赋值。

函数解说

  • GetStaticFieldID():用于获取 静态属性 IDjfieldID
  • GetStaticField():用于获取jclass中的属性。
  • SetStaticField():用于给jclass中的属性赋值。

你可能感兴趣的:(★06.访问属性)