2.4.2 数据类型转换
最后更新于:2022-04-02 05:48:15
通过前面的分析,解决了JNI函数的注册问题。下面来研究数据类型转换的问题。
在Java中调用native函数传递的参数是Java数据类型,那么这些参数类型到了JNI层会变成什么呢?
Java数据类型分为基本数据类型和引用数据类型两种,JNI层也是区别对待这二者的。先来看基本数据类型的转换。
(1)基本类型的转换
基本类型的转换很简单,可用表2-1表示:
:-: 表2-1 基本数据类型转换关系表
| Java | Native类型 | 符号属性 | 字长 |
| --- | --- | --- | --- |
|boolean | jboolean | 无符号 | 8位 |
| byte | jbyte | 无符号 | 8位 |
| char | jchar | 无符号| 16位 |
| short | jshort | 有符号| 16位 |
| int | jint |有符号 | 32位 |
| long | jlong | 有符号 | 64位 |
| float | jfloat | 有符号 | 32位 |
| double | jdouble| 有符号 | 64位 |
上面列出了Java基本数据类型和JNI层数据类型对应的转换关系,非常简单。不过,应务必注意,转换成Native类型后对应数据类型的字长,例如jchar在Native语言中是16位,占两个字节,这和普通的char占一个字节的情况完全不一样。
接下来看Java引用数据类型的转换。
(2)引用数据类型的转换
引用数据类型的转换如表2-2所示:
:-: 表2-2 Java引用数据类型转换关系表
| Java引用类型 | Native类型 | Java引用类型 | Native类型 |
| --- | --- | --- | --- |
| All objects | jobject | char[] |jcharArray |
| java.lang.Class实例 | jclass | short[] | jshortArray |
| java.lang.String实例 | jstring | int[] | jintArray |
| Object[] | jobjectArray | long[] | jlongArray |
| boolean[] | jbooleanArray | float[] | floatArray |
| byte[] |jbyteArray | double[] | jdoubleArray |
| java.lang.Throwable实例 | jthrowable | | |
由上表可知:
- 除了Java中基本数据类型的数组、Class、String和Throwable外,其余所有Java对象的数据类型在JNI中都用jobject表示。
这一点太让人惊讶了!看processFile这个函数:
~~~
//Java层processFile有三个参数。
processFile(String path, StringmimeType,MediaScannerClient client);
//JNI层对应的函数,最后三个参数和processFile的参数对应。
android_media_MediaScanner_processFile(JNIEnv*env, jobject thiz,
jstring path, jstring mimeType, jobject client)
~~~
从上面这段代码中可以发现:
- Java的String类型在JNI层对应为jstring。
- Java的MediaScannerClient类型在JNI层对应为jobject。
如果对象类型都用jobject表示,就好比是Native层的void*类型一样,对码农来说,是完全透明的。既然是透明的,那该如何使用和操作它们呢?在回答这个问题之前,再来仔细看看上面那个android_media_MediaScanner_processFile函数,代码如下:
~~~
/*
Java中的processFile只有三个参数,为什么JNI层对应的函数会有五个参数呢?第一个参数中的JNIEnv是什么?稍后介绍。第二个参数jobject代表Java层的MediaScanner对象,它表示
是在哪个MediaScanner对象上调用的processFile。如果Java层是static函数的话,那么
这个参数将是jclass,表示是在调用哪个Java Class的静态函数。
*/
android_media_MediaScanner_processFile(JNIEnv*env,
jobject thiz,
jstring path, jstring mimeType, jobject client)
~~~
上面的代码,引出了下面几节的主角JNIEnv。
';