1、GetStringUTFChars
用于將 Java 字符串(jstring
)轉換為 UTF-8 編碼的 C 風格字符串(const char*
)。
必須在使用完后調用?ReleaseStringUTFChars
?釋放內存,否則可能導致內存泄漏。
std::string data_converter::convertJavaStringToCpp(JNIEnv* env, jstring jStr) {const char* cStr = env->GetStringUTFChars(jStr, nullptr);std::string result(cStr);env->ReleaseStringUTFChars(jStr, cStr);return result;
}
2、NewStringUTF
用于將?C/C++ 的 UTF-8 字符串?轉換為 Java 的?jstring
?對象。
const char *cStr = "Hello from C++! 你好!";
jstring javaStr = env->NewStringUTF(cStr);
3、GetArrayLength
用于獲取 Java 數組的長度。
JNIEXPORT jint JNICALL Java_Example_getArrayLength(JNIEnv *env, jobject obj, jintArray arr) {jsize length = env->GetArrayLength(arr);return length;
}
4、GetObjectArrayElement
用于從 Java 對象數組中獲取指定索引處的元素。
對于基本類型數組(如 int[], float[] 等),不能直接使用 GetObjectArrayElement,而應該使用對應的函數如 GetIntArrayElements。
JNIEXPORT void JNICALL Java_Example_printArrayElements(JNIEnv *env, jobject obj, jobjectArray arr) {jsize length = env->GetArrayLength(arr);for (jsize i = 0; i < length; i++) {jobject element = env->GetObjectArrayElement(arr, i);// 對 element 進行操作...}
}
5、GetByteArrayRegion
用于將 Java 字節數組 (jbyteArray
) 的一部分或全部復制到 C/C++ 的本地緩沖區中。
JNIEXPORT void JNICALL Java_Example_processByteArray(JNIEnv *env, jobject obj, jbyteArray javaArray)
{// 獲取數組長度jsize length = env->GetArrayLength(javaArray);// 分配本地緩沖區jbyte *buffer = new jbyte[length];// 復制整個數組到本地緩沖區env->GetByteArrayRegion(javaArray, 0, length, buffer);// 處理數據...for (jsize i = 0; i < length; i++) {// 處理 buffer[i]...}// 釋放本地緩沖區delete[] buffer;
}
6、(void)env;
?和?(void)instance;
這兩行是用于?顯式忽略未使用參數?的編程技巧。
static void saveDeviceID(JNIEnv* env, jobject instance, jstring devID)
{(void)env; // 明確表示不使用 env 參數(void)instance; // 明確表示不使用 instance 參數// ...
}
7、GetObjectClass
用于在 C/C++ 代碼中獲取 Java 對象的類引用。它通常在編寫本地方法(native methods)時使用。
#include <jni.h>JNIEXPORT void JNICALL Java_Example_printClassName(JNIEnv *env, jobject obj) {// 獲取傳入對象的類jclass cls = env->GetObjectClass(obj);// 獲取類名jmethodID mid_getName = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");jstring name = (jstring)env->CallObjectMethod(cls, mid_getName);const char *str = env->GetStringUTFChars(name, NULL);printf("Class name: %s\n", str);env->ReleaseStringUTFChars(name, str);
}
替代方案
如果你想獲取某個已知類的引用(而不是通過對象實例),可以使用?FindClass()
?函數:
jclass cls = env->FindClass("java/lang/String");
GetObjectClass()
?主要用于當你已經有一個對象實例但需要訪問其類信息時使用。
8、NewGlobalRef
用于創建一個全局引用(global reference)到 Java 對象。全局引用在本地代碼中跨多個本地方法調用時保持有效,直到顯式釋放。
// 全局變量存儲引用
jclass globalClassRef;JNIEXPORT void JNICALL Java_Example_init(JNIEnv *env, jobject obj) {// 獲取局部引用jclass localClassRef = env->GetObjectClass(obj);// 創建全局引用globalClassRef = (jclass)env->NewGlobalRef(localClassRef);// 局部引用不再需要時可以刪除env->DeleteLocalRef(localClassRef);
}JNIEXPORT void JNICALL Java_Example_cleanup(JNIEnv *env, jobject obj) {// 不再需要時釋放全局引用if (globalClassRef != NULL) {env->DeleteGlobalRef(globalClassRef);globalClassRef = NULL;}
}
相關函數
DeleteGlobalRef()
: 釋放全局引用NewLocalRef()
: 創建局部引用NewWeakGlobalRef()
: 創建弱全局引用
9、
NetworkManagerCallback() = default;virtual ~NetworkManagerCallback() = default;NetworkManagerCallback(const NetworkManagerCallback& other) = delete;NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;
這幾行代碼展示了一個類中常見的特殊成員函數的聲明和定義方式。
NetworkManagerCallback() = default;
使用編譯器生成的默認構造函數
示例:當創建
NetworkManagerCallback
對象時,會調用這個默認構造函數
NetworkManagerCallback callback; // 使用默認構造函數
virtual ~NetworkManagerCallback() = default;
聲明虛析構函數并使用默認實現
使得這個類可以作為基類被繼承,且能正確調用派生類的析構函數
示例:
class DerivedCallback : public NetworkManagerCallback {~DerivedCallback() override { /* 清理資源 */ } };
NetworkManagerCallback(const NetworkManagerCallback& other) = delete;
禁用拷貝構造函數
示例:以下代碼會編譯錯誤
NetworkManagerCallback cb1; NetworkManagerCallback cb2(cb1); // 錯誤:拷貝構造函數被刪除
NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;
禁用拷貝賦值運算符
示例:以下代碼會編譯錯誤
NetworkManagerCallback cb1; NetworkManagerCallback cb2; cb2 = cb1; // 錯誤:拷貝賦值運算符被刪除
這種模式通常用于:
需要作為基類但不需要拷貝功能的類(如回調接口)
只允許移動不允許拷貝的類
單例模式實現