JNI - 将表示基本Java对象(布尔值)的jobject转换为本机基本类型(bool)

Gra*_*eme 5 performance java-native-interface android-ndk

我想我已经设法将大部分问题都纳入了这个问题的标题!

我在我的本机C++代码中从Java中撤回一个Object:

jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);
Run Code Online (Sandbox Code Playgroud)

我可以使用以下方法检查返回对象是否是本机类型之一:

jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }
Run Code Online (Sandbox Code Playgroud)

所以,我现在有一个jobject,我知道它是一个布尔值(注意大写字母B) - 问题是,最有效的方法是什么(考虑到我已经在我的本机代码中有了jobject)将它转换为a bool.类型转换不起作用,这是有道理的.

虽然上面的例子是一个布尔我也想转换Character-> char,Short-> short,Integer-> int,Float-> float,Double-> double.

(一旦我实现了它,我将发布一个回答这个做Boolean.booleanValue())

fad*_*den 5

你有两个选择.

选项#1是您在自我回答中编写的内容:使用为每个类定义的公共方法来提取原始值.

选项#2更快但不严格合法:直接访问内部字段.对于Boolean,这将是Boolean.value.对于每个原始框类,您有"value"字段的fieldID,您只需直接读取该字段.(JNI高兴地忽略了它被宣布为私有的事实.你也可以写入"最终"字段并做其他属于"非常糟糕的想法"类别的东西.)

"value"字段的名称不太可能改变,因为这会破坏序列化.所以不建议正式使用,但在实践中,如果需要,你可以侥幸逃脱.

无论哪种方式,您应该缓存jmethodID/jfieldID值,而不是每次都查找它们(查找相对昂贵).

您也可以使用较便宜的IsSameObject函数而不是IsInstanceof,因为box类是"final".这需要进行额外的GetObjectClass调用以获取valueObject的类,但在进行各种比较之前,您只需执行一次.

顺便说一句,小心你使用"char".在上面的示例中,您将CallCharMethod(一个16位UTF-16值)的结果转换为char(一个8位值).记住,char!= jchar(除非你以某种方式为宽字符配置),long!= jlong​​(除非你用64位长编译).

  • 你在这里问的各种各样的东西可能无法从一本书中学到.如果你有时间编写自己的VM,你肯定会学到很多东西; 如果没有,只需编写大量代码,然后尝试弄清楚它为什么会被破坏.:-) (2认同)