实例属性 与 静态属性
-
实例属性:同一个类每一个对象都会拥有一份的属性。
-
静态属性:同一个类的所有对象都共享的属性。
实例属性
简单示例
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
。
- 创建查看 属性描述符 的便捷工具,可以避免手写 属性描述符 :
- File -> Settings -> External Tools。
- 点击 “+” 按钮。
-
Name :
输出类描述符
。
-
Group :
JNI
。
-
Options : 全部勾选。
-
Show in : 全部勾选。
-
Program :
$JDKPath$\bin\javap.exe
。
-
Parameters :
-s -p $FileClass$
。-p
选项用于输出私有成员。
-
Working directory :
$OutputPath$
。
- 点击确定。
- 示例步骤:
- 使用
jobject
获取其对应的jclass
。
- 使用
jclass
、 属性名 和 属性描述符 来获取属性的jfieldID
。
- 使用
jfieldID
和jobject
来获取属性值。
- 使用
jobject
、jfieldID
和 新属性值 来给属性赋值。
函数解说
-
GetObjectClass()
:用于获取jobject
对应的jclass
。
-
GetFieldID()
:用于获取 实例属性 IDjfieldID
。
-
Get<Type>Field()
:用于获取jobject
中的属性。
-
Set<Type>Field()
:用于给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);
}
示例解说
- 示例步骤:
- 使用
jobject
获取其对应的jclass
。
- 使用
jclass
、 属性名 和 属性描述符 来获取属性的jfieldID
。
- 使用
jfieldID
和jclass
来获取属性值。
- 使用
jclass
、jfieldID
和 新属性值 来给属性赋值。
函数解说
-
GetStaticFieldID()
:用于获取 静态属性 IDjfieldID
。
-
GetStatic<Type>Field()
:用于获取jclass
中的属性。
-
SetStatic<Type>Field()
:用于给jclass
中的属性赋值。