我认为我设法将大部分问题都纳入了这个问题的标题!
我在我的原生C ++代码中从Java中撤回一个Object:
jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);
我可以使用以下内容检查返回对象是否是本机类型之一:
jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }
所以,我现在有一个jobject,我知道它是一个布尔值(注意大写字母B) - 问题是,最有效的方法是什么(考虑到我已经在我的本机代码中有了jobject)将它转换为一个bool
。类型转换不起作用。
虽然上面的例子是布尔值,但我也想转换字符 - > char,短 - >短,整数 - > int,Float-> float,Double-> double。
(一旦我实现了它,我将发布一个回答,这个做布尔值。布尔值。)
答案 0 :(得分: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位长编译)。答案 1 :(得分:1)
如果我没有更多输入,这是我将要使用的解决方案。希望这不是困难,但知道JNI我认为它可能是:
if (env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE)
{
jmethodID booleanValueMID = env->GetMethodID(boolClass, "booleanValue", "()Z");
bool booleanValue = (bool) env->CallBooleanMethod(valueObject, booleanValueMID);
addBoolean(key, booleanValue);
}
else if(env->IsInstanceOf(valueObject, charClass) == JNI_TRUE)
{
jmethodID characterValueMID = env->GetMethodID(charClass, "charValue", "()C");
char characterValue = (char) env->CallCharMethod(valueObject, characterValueMID);
addChar (key, characterValue);
}
答案 2 :(得分:0)
一般来说,我写jni是为了获得更好的性能。 如何获得更好的性能?使用asm,原始类型和几个方法调用。 我建议设计你的方法返回类型可以在c / c ++中使用,比如 jint,jlong,jboolean,jbyte和jchar等。
冗余函数调用和转换将导致低效且无法维护的实现。