前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JNI:取得Java属性和设置Java属性值

JNI:取得Java属性和设置Java属性值

作者头像
BUG弄潮儿
发布2022-03-08 10:46:12
1.9K0
发布2022-03-08 10:46:12
举报
文章被收录于专栏:JAVA乐园

1. 取得Java属性/设定Java属性值

  • 获得了相应属性的jfieldID之后,就可以使用
代码语言:javascript
复制
Set<TYPE>Field
Get<TYPE>Field
SetStatic<TYPE>Field
GetStatic<TYPT>Field

等函数来对Java属性进行操作了。

  • 类实例方法
代码语言:javascript
复制
Set/GetBooleanField
Set/GetByteField
Set/GetDoubleField
Set/GetFloatField
Set/GetIntField
Set/GetLongField
Set/GetShortField
Set/GetObjectField
  • 类静态方法
代码语言:javascript
复制
Set/GetStaticBooleanField
Set/GetStaticByteField
Set/GetStaticDoubleField
Set/GetStaticFloatField
Set/GetStaticIntField
Set/GetStaticLongField
Set/GetStaticShortField
Set/GetStaticObjectField
  • 怎样获取数组的属性呢?

可以使用GetObjectField来获取数组类型的属性。不过JNI提供了一系列方法获取数组的属性,后续介绍。

2. 案例

在C/C++中修改Java中的属性

代码语言:javascript
复制
package com.omg;

public class TestNative {

          public int number;

          public native void sayHello();

}

C++代码

代码语言:javascript
复制
jclass clazz_TestNative = env->GetObjectClass( obj);
jfieldID id_number = env->GetFieldID(clazz_TestNative, "number", "I");
jint number = env->GetIntFiled(obj, id_number);
count << number << endl;
env->SetIntField(obj, id_number, 100L);

3. Java方法调用

  • JNIEnv提供了众多的 Call<TYPE>Method 与 CallStatic<TYPE>Method,还有CallNonvirtual<TYPE>Method函数。需要通过GetMethodID取得相应方法的jmethodID来传入上述函数的参数中。
  • 调用实例方法的三种形式
代码语言:javascript
复制
Call<TYPE>Method( jobject obj, jmethodID id, ...);
Call<TYPE>MethodV( jobject obj, jmethodID id, va_list lst);
Call<TYPE>MethodA( jobject obj, jmethodID id, jvalue* v);

第一种是最常用的方式 第二种是当调用这个函数的时候,有一个指向参数表的va_list变量时使用(不常用) 第三种是当调用这个函数的时候,有一个指向jvalue或者jvalue数组的指针时使用

调用静态方法的三种形式

代码语言:javascript
复制
CallStatic<TYPE>Method( jclass clazz, jmethodID id, ...);
CallStatic<TYPE>MethodV( jclass clazz, jmethodID id, va_list lst);
CallStatic<TYPE>MethodA( jclass clazz, jmethodID id, jvalue* v);

伪代码

代码语言:javascript
复制
java:
public boolean function(int i, double d, char c){
     //......
}

C
env->CallBooleanMethod(obj, id_function, 100L, 1.11, L'3')

jvalue * args = new jvalue[3];
args[0].i = 100L;
args[1].d = 3.44;
args[2].c = L'3';
env->CallBooleanMethod( obj, id_function, args);
delete [] args;

4. 案例

在C/C++中代用Java中的方法

Java代码

代码语言:javascript
复制
package com.omg;

public class TestNative {
    public max(double num1, double num2){
        return num1 > num2 ? num1 : num2;
    }
}

C++代码

代码语言:javascript
复制
jclass clazz_TestNative = env->GetObjectClass( obj );
jmethodID id_max = env->GetMetodID( clazz_TestNative, obj, "(DD)D");
jdouble maxVal = env->GetDoubleMethod(obj, id_max, 2.1, 3.14);
cout << maxVal << endl;

5. CallNonvirtual<TYPE>Method

有如下Java代码

代码语言:javascript
复制
public class Father {

    public void function(){
            System.out.println("Father function");
        }
    }
  
   public class Child extends Father {
      public void function(){
        System.out.println("Child function");
    }

}

想想这段Java代码调用的是哪个类的方法?

代码语言:javascript
复制
Father p = new Child();
p.function();

如果想调用父类的function是没有办法的

有如下C++代码

代码语言:javascript
复制
class Father {

    public:
    void function(){
        cout << "Father function" <<endl;
    }

}

  class Child : public Father {
      public:
       void function(){
        cout << "Child function" <<endl;
    }

}

想想这段代码调用的是哪个类的成员函数?(调用的是父类的函数)

代码语言:javascript
复制
Father* p = new Child();
p->function();

C++有虚函数的概念,修改一下父类加一个 virtual

代码语言:javascript
复制
class Father {

    public:
    virtual void function(){
        cout << "Father function" <<endl;
   }

}

class Child : public Father {

    public:
    void function(){
          cout << "Child function" <<endl;
     }

}

再想想这段代码调用的是哪个类的成员函数?(调用的是子类的函数)

代码语言:javascript
复制
Father* p = new Child();
p->function();

在Java语言中,所有的函数都是虚函数

  • 在JNI中定义了CallNonvirtual<TYPE>Method就能实现子类对象调用父类方法的功能,如果想要调用一个对象的父类的方法,而不是子类的重写(over write)的方法的话,就可以使用CallNonVirtual<TYPE>Method
  • 要使用CallNonVirtual<TYPE>Method,首先要取得父类及要调用的父类的方法的jmethodID。然后传入到这个函数就能通过子类对象调用被重写(over write)的父类的方法

5. 案例

代码语言:javascript
复制
package com.omg;


public class Father {

    public void function() {
       System.out.println("Father function");
    } 

}



package com.omg;


public class Child extends Father {

    public void function() {
        System.out.println("Child function");
    }

}

测试

Java定义成员变量

代码语言:javascript
复制
public Father p = new Child();

C++代码

代码语言:javascript
复制
jclass clazz_TestNative = env->GetObjectClass( obj );
jfieldID id_p = env->GetFieldID(clazz_TestNative, "p", "Lcom/omg/Father;");
jobject p = env->GetObjectField(obj, id_p);

jclass clazz_Father = env->FindClass( "Lcom/omg/Father;" );
jmethodID id_Father_function = env->GetMethodID(clazz_Father, "function", "()V");

env->CallVoidMethod(p, id_Father_function);

env->CallNonvirtualVoidMethod(p, clazz_Father, id_Father_function);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BUG弄潮儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 取得Java属性/设定Java属性值
  • 2. 案例
  • 5. 案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档