Android JNI開發系列(十)JNI訪問 Java 實例變量和靜態變量

JNI訪問 Java 實例變量和靜態變量

Java 中的實例變量和靜態變量,在本地代碼中如何來訪問和修改。靜態變量也稱爲類變量(屬性),在全部實例對象中共享同一份數據,能夠直接經過類名.變量名來訪問。實例變量也稱爲成員變量(屬性),每一個實例都擁有一份實例變量數據的拷貝,它們之間修改後的數據互不影響。java

直接上代碼:android

JAVA

public class Person {

    //成員變量 
    private String hobby;

    //靜態變量
    private static int happiness;

    public String getHobby() {
        return hobby;
    }

    public static int getHappiness() {
        return happiness;
    }

    //Native方法中設置成員變量的值
    public native boolean setHobby();
    
    //Native方法中設置靜態變量的值
    public native boolean setHappiness();
}

Native

JNIEXPORT jboolean JNICALL
Java_org_professor_jni_bean_Person_setHobby(JNIEnv *env, jobject instance) {

//1.獲取類類型的Class對象
jclass personClass = (*env)->FindClass(env, "org/professor/jni/Person");
if (NULL == personClass) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND CLASS");
    return JNI_FALSE;
}
//2.獲取屬性ID
jfieldID hobbyFiledID = (*env)->GetFieldID(env, personClass, "hobby", "Ljava/long/String");

if (NULL == hobbyFiledID) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND Hobby FiledID");
    return JNI_FALSE;
}

//3.實例屬性,經過對象獲取屬性值
jstring hobbyFiledStr = (*env)->GetObjectField(env, instance, hobbyFiledID);
if (NULL != hobbyFiledStr) {
    const char *hobby = (*env)->GetStringUTFChars(env, hobbyFiledStr, NULL);
    if (NULL != hobby) {
        __android_log_print(ANDROID_LOG_ERROR, "PERSON Hobby", hobby);
        (*env)->ReleaseStringChars(env, hobbyFiledStr, hobby);
    }
}
//4.設置屬性值
jstring jHobby = (*env)->NewStringUTF(env, "BASKETBALL,RUN");
(*env)->SetObjectField(env, instance, hobbyFiledID, jHobby);
//5.刪除局部引用變量
(*env)->DeleteLocalRef(env, personClass);
(*env)->DeleteLocalRef(env, hobbyFiledStr);
(*env)->DeleteLocalRef(env, jHobby);
return JNI_TRUE;
}


JNIEXPORT jboolean JNICALL
Java_org_professor_jni_bean_Person_setHappiness(JNIEnv *env, jobject instance) {

//1.獲取類類型的Class對象
jclass personClass = (*env)->FindClass(env, "org/professor/jni/Person");
if (NULL == personClass) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND CLASS");
    return JNI_FALSE;
}
//2.獲取屬性ID

jfieldID happinessFiledID = (*env)->GetStaticFieldID(env, personClass, "happiness", "I");

if (NULL == happinessFiledID) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND Happiness FiledID");
    return JNI_FALSE;
}

//3.獲取靜態屬性值
jint happinessValue = (*env)->GetStaticIntField(env, personClass, happinessFiledID);
if (NULL != happinessValue) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON happinessValue = %d",
                        (const char *) happinessValue);
}

//4.設置靜態屬性值
(*env)->SetStaticIntField(env, personClass, happinessFiledID, 80);

//5.刪除本地局部引用表,基本數據類型不須要
(*env)->DeleteLocalRef(env, personClass);
return JNI_TRUE;
}

小結

  • 因爲JNI 函數是直接操做JVM中的數據結構,不受 Java訪問修飾符的限制。即,Native代碼中調用 JNI函數能夠訪問 Java 對象中的非 public 屬性和方法
  • 訪問和修改實例變量操做步聚
    • 調用 GetObjectClass 函數獲取實例對象的 Class 引用
    • 調用 GetFieldID 函數獲取 Class 引用中某個實例變量的 ID
    • 調用 GetXXXField 函數獲取變量的值,須要傳入實例變量所屬對象和變量 ID
    • 調用 SetXXXField 函數修改變量的值,須要傳入實例變量所屬對象、變量 ID 和變量的值
  • 訪問和修改靜態變量操做步聚:
    • 調用 FindClass 函數獲取類的 Class 引用
    • 調用 GetStaticFieldID 函數獲取 Class 引用中某個靜態變量 ID
    • 調用 GetStaticXXXField 函數獲取靜態變量的值,須要傳入變量所屬 Class 的引用和變量 ID
    • 調用 SetStaticXXXField 函數設置靜態變量的值,須要傳入變量所屬 Class 的引用、變量 ID和變量的值
相關文章
相關標籤/搜索