本页内容

QJniObject Class

Java 本机接口(JNI)的一个便捷封装类。更多内容...

标题: #include <QJniObject>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core
自: Qt 6.1

公共函数

QJniObject()
QJniObject(const char *className)
QJniObject(jclass clazz)
QJniObject(jobject object)
(since 6.4) QJniObject(const char *className, Args &&... args)
(since 6.4) QJniObject(jclass clazz, Args &&... args)
QJniObject(const char *className, const char *signature, ...)
QJniObject(jclass clazz, const char *signature, ...)
QJniObject(const QJniObject &other)
QJniObject(QJniObject &&other)
~QJniObject()
(since 6.4) auto callMethod(const char *methodName, Args &&... args) const
(since 6.4) auto callMethod(const char *methodName, const char *signature, Args &&... args) const
(since 6.4) QJniObject callObjectMethod(const char *methodName, Args &&... args) const
QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const
(since 6.2) QByteArray className() const
auto getField(const char *fieldName) const
QJniObject getObjectField(const char *fieldName) const
QJniObject getObjectField(const char *fieldName, const char *signature) const
bool isValid() const
jobject object() const
T object() const
(since 6.2) jclass objectClass() const
auto setField(const char *fieldName, Type value)
auto setField(const char *fieldName, const char *signature, Type value)
(since 6.8) void swap(QJniObject &other)
QString toString() const
QJniObject &operator=(QJniObject &&other)
QJniObject &operator=(T object)
QJniObject &operator=(const QJniObject &other)

静态公共成员

(since 6.7) auto callStaticMethod(const char *methodName, Args &&... args)
(since 6.4) auto callStaticMethod(const char *className, const char *methodName, Args &&... args)
(since 6.4) auto callStaticMethod(jclass clazz, const char *methodName, Args &&... args)
(since 6.4) auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&... args)
(since 6.4) auto callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&... args)
auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&... args)
(since 6.4) QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&... args)
(since 6.4) QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&... args)
QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...)
QJniObject callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...)
QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, const char *signature, ...)
(since 6.4) auto construct(Args &&... args)
QJniObject fromLocalRef(jobject localRef)
QJniObject fromString(const QString &string)
auto getStaticField(const char *fieldName)
auto getStaticField(const char *className, const char *fieldName)
auto getStaticField(jclass clazz, const char *fieldName)
QJniObject getStaticObjectField(const char *className, const char *fieldName)
QJniObject getStaticObjectField(jclass clazz, const char *fieldName)
QJniObject getStaticObjectField(const char *className, const char *fieldName, const char *signature)
QJniObject getStaticObjectField(jclass clazz, const char *fieldName, const char *signature)
bool isClassAvailable(const char *className)
auto setStaticField(const char *fieldName, Type value)
auto setStaticField(const char *className, const char *fieldName, Type value)
auto setStaticField(jclass clazz, const char *fieldName, Type value)
auto setStaticField(const char *className, const char *fieldName, const char *signature, Type value)
auto setStaticField(jclass clazz, const char *fieldName, const char *signature, Type value)
bool operator!=(const QJniObject &o1, const QJniObject &o2)
bool operator==(const QJniObject &o1, const QJniObject &o2)

详细说明

QJniObject 类封装了对 Java 对象的引用,确保该对象不会被垃圾回收,并提供了对大多数JNIEnv 方法调用(成员方法、静态方法)和字段(设置器、获取器)的访问。它消除了通常在通过 JNI 直接访问时,每项操作所需的大量冗余代码。 被调用的 Java 方法抛出的异常默认会被清除,但自 Qt 6.11 起,调用方也可以对其进行处理。

注意:此 API 专为在 Android 上使用而设计并经过测试。尚未在其他平台上进行测试。

方法签名

QJniObject 提供了便捷函数,这些函数会根据提供的或推断出的模板参数使用正确的签名。

jint x = QJniObject::callMethod<jint>("getSize");
QJniObject::callMethod<void>("touch");
jint ret = jString1.callMethod<jint>("compareToIgnoreCase", jString2.object<jstring>());

这些函数是可变参数模板,编译器将根据实际参数类型推导出签名。只需显式指定返回类型即可。对于接受JNI types 的函数,以及使用QtJniTypes 类型映射声明的类型,QJniObject 可以推导出其签名字符串。

// Java class
package org.qtproject.qt;
class TestClass
{
    static TestClass create() { ... }
    static String fromNumber(int x) { ... }
    static String[] stringArray(String s1, String s2) { ... }
}
// C++ code
Q_DECLARE_JNI_CLASS(TestClass, "org/qtproject/qt/TestClass")

// ...
using namespace QtJniTypes;
TestClass testClass = TestClass::callStaticMethod<TestClass>("create");

这使得 C++ 代码能够处理任意的 Java 和 Android 类型,而无需显式创建 JNI 签名字符串。

显式 JNI 签名

您也可以自行提供签名。在这种情况下,签名必须与您要调用的函数相匹配,这一点非常重要。

  • 类名必须是完全限定的,例如:"java/lang/String" 。
  • 方法签名应写为"(ArgumentsTypes)ReturnType" ,详见JNI Types 。
  • 所有对象类型均以 QJniObject 形式返回。

下面的示例演示了如何调用不同的静态函数:

签名结构为"(ArgumentsTypes)ReturnType" 。签名中的数组类型必须带有[ 前缀,而完全限定的Object 类型名必须带有L 前缀和; 后缀。create 函数的签名是"()Lorg/qtproject/qt/TestClass; 。第二个和第三个函数的签名分别是"(I)Ljava/lang/String;" 和"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;" 。

我们可以像这样调用create() 函数:

// C++ code
QJniObject testClass = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
                                                          "create",
                                                          "()Lorg/qtproject/qt/TestClass;");

对于第二个和第三个函数,我们可以借助 QJniObject 的模板方法来生成隐式签名字符串,但也可以显式地传递签名字符串:

// C++ code
QJniObject stringNumber = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
                                                             "fromNumber",
                                                             "(I)Ljava/lang/String;", 10);

要使隐式签名生成正常工作,我们需要显式指定返回类型:

// C++ code
QJniObject string1 = QJniObject::fromString("String1");
QJniObject string2 = QJniObject::fromString("String2");
QJniObject stringArray = QJniObject::callStaticObjectMethod<jobjectArray>(
                                                            "org/qtproject/qt/TestClass",
                                                            "stringArray",
                                                            string1.object<jstring>(),
                                                            string2.object<jstring>());

请注意,尽管第一个模板参数指定了 Java 函数的返回类型,但该方法仍会返回一个 QJniObject。

处理 Java 异常

在调用可能抛出异常的 Java 函数后,必须在继续执行之前检查、处理并清除任何异常。 所有 QJniObject 函数都能在内部通过报告和清除异常来处理异常。这包括 JNI 异常(例如尝试调用不存在的函数,或参数错误时抛出的异常),以及方法为报告错误或返回失败信息而抛出的异常。

从 Qt 6.11 开始,客户端代码可以选择在每次调用中显式处理异常。为此,请将 C++ 23 中的 `std::expected ` 作为返回类型,将值类型设为预期类型,并将 `jthrowable ` 设为错误类型。 例如,如果尝试通过android.provider.Settings.Secure 类型读取某个设置值,而该设置不存在,则可能会抛出异常。

Q_DECLARE_JNI_CLASS(SettingsSecure, "android/provider/Settings$Secure")
using namespace QtJniTypes;

QString enabledInputMethods()
{
    ContentResolver resolver;
    SettingsSecure settings;

    auto defaultInputMethods = settings.callMethod<std::expected<QString, jthrowable>>(
        "getString", resolver, u"enabled_input_methods"_s
    );
    if (defaultInputMethods)
        return defaultInputMethods.value();
    QStringList stackTrace = QJniEnvironment::stackTrace(defaultInputMethods.error());
}

您可以使用任何行为与std::expected 类似的类型,因此即使不使用C++23,也可以显式处理异常。唯一的要求是该类型需声明三个嵌套类型value_type 、error_type 和unexpected_type ,并且能够从值类型及其包含jthrowable 的unexpected_type 进行构造。

注意: 当直接使用JNIEnv 进行JNI调用时,用户 必须手动处理异常。在存在待处理异常的情况下进行其他JNI调用是不安全的。有关更多信息,请参阅QJniEnvironment::checkAndClearExceptions()。

Java 本机方法

Java 本机方法使得从 Java 调用本机代码成为可能,具体操作是在 Java 中创建函数声明,并在其前缀添加native 关键字。在从 Java 调用本机函数之前,您需要将 Java 本机函数映射到代码中的本机函数。可以通过调用QJniEnvironment::registerNativeMethods() 来完成函数映射。

下面的示例演示了如何实现这一点。

Java 实现:

class FooJavaClass
{
    public static void foo(int x)
    {
        if (x < 100)
            callNativeOne(x);
        else
            callNativeTwo(x);
    }

private static native void callNativeOne(int x);
private static native void callNativeTwo(int x);

}

C++ 实现:

static voidfromJavaOne(JNIEnv*env,jobject thiz,jint x)
{
    Q_UNUSED(env);
    Q_UNUSED(thiz);
    qDebug() << x << "< 100";
}

static voidfromJavaTwo(JNIEnv*env,jobject thiz,jint x)
{
    Q_UNUSED(env);
    Q_UNUSED(thiz);
    qDebug() << x << ">= 100";
}

voidfoo()
{
    // 首先注册本机方法,最好在应用程序启动时完成
    constJNINativeMethod methods[] =
                {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
                 {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
    QJniEnvironment env;
    env.registerNativeMethods("my/java/project/FooJavaClass",methods, 2);

    // 调用 Java 方法,该方法将回调至 C++ 函数
    QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 10);  // 输出:10 < 100
    QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 100);// 输出:100 >= 100
}

Java 对象的生命周期

从 Java 接收的大多数objects 都是局部引用,其有效期仅持续到您从本机方法返回为止。此后,该对象将进入垃圾回收范围。如果您的代码在循环中创建了大量局部引用,则应在每次迭代后手动将其删除,否则可能会导致内存不足。 有关更多信息,请参阅《JNI 设计概述:全局和局部引用》。在本机方法作用域外创建的局部引用必须手动删除,因为我们使用了 `AttachCurrentThread`,垃圾回收器不会自动释放它们。有关更多信息,请参阅《JNI 提示:局部和全局引用》。

若要保持 Java 对象存活,您需要为该对象创建一个新的全局引用并在使用完毕后释放它,或者构建一个新的 QJniObject 并让其管理该 Java 对象的生命周期。

注意: QJniObject 仅管理其自身的引用;若您通过全局或局部引用构建 QJniObject,该引用将不会由 QJniObject 释放。

JNI 类型

对象类型

类型签名
jobjectLjava/lang/Object;
jclassLjava/lang/Class;
jstringLjava/lang/String;
jthrowableLjava/lang/Throwable;
jobjectArray[Ljava/lang/Object;
jarray[<类型>
jbooleanArray[Z
jbyteArray[B
jcharArray[C
jshortArray[S
jintArray[I
jlongArray[J
jfloatArray[F
jdoubleArray[D

基本类型

类型签名
jbooleanZ
jbyteB
jcharC
jshortS
jintI
jlongJ
jfloatF
jdoubleD

其他

类型签名
voidV
自定义类型L<完全限定名称>;

有关 JNI 的更多信息,请参阅《Java 本机接口规范》。

另请参阅 QJniEnvironment 和object()。

成员函数文档

QJniObject::QJniObject()

构建一个无效的 JNI 对象。

另请参阅 isValid()。

[explicit] QJniObject::QJniObject(const char *className)

通过调用className 的默认构造函数来创建一个新的JNI对象。

QJniObject myJavaString("java/lang/String");

[explicit] QJniObject::QJniObject(jclass clazz)

通过调用clazz 的默认构造函数来创建一个新的JNI对象。

注意:QJniObject 将创建对类clazz 的新引用,并在其销毁时释放该引用。在 QJniObject 外部创建的对该类的引用需由调用方自行管理。

QJniObject::QJniObject(jobject object)

围绕 Java 对象object 构建一个新的 JNI 对象。

注意:QJniObject 将持有对 Java 对象object 的引用,并在销毁时释放该引用。QJniObject 外部对 Java 对象object 的任何引用均需由调用方自行管理。在大多数情况下,除非您打算自行管理该局部引用,否则切勿使用局部引用调用此函数。 有关将局部引用转换为 QJniObject 的方法,请参阅QJniObject::fromLocalRef()。

另请参阅 fromLocalRef()。

[explicit, since 6.4] template <typename... Args> QJniObject::QJniObject(const char *className, Args &&... args)

通过调用className 的构造函数并传入参数args 来构建一个新的JNI对象。只有当所有args 已知JNI Types 时,该构造函数才可用。

QJniEnvironment env;
char* str = "Hello";
jstring myJStringArg = env->NewStringUTF(str);
QJniObject myNewJavaString("java/lang/String", myJStringArg);

该函数在 Qt 6.4 中引入。

[explicit, since 6.4] template <typename... Args> QJniObject::QJniObject(jclass clazz, Args &&... args)

通过调用构造函数并传入参数args ,从clazz 构建一个新的JNI对象。只有当所有args 均已知时,该构造函数才可用JNI Types 。

QJniEnvironment env;
jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
QJniObject(myClazz, 3);

该函数在 Qt 6.4 中引入。

[explicit] QJniObject::QJniObject(const char *className, const char *signature, ...)

通过调用className 的构造函数来创建一个新的JNI对象,其中signature 用于指定后续参数的类型。

QJniEnvironment env;
char* str = "Hello";
jstring myJStringArg = env->NewStringUTF(str);
QJniObject myNewJavaString("java/lang/String", "(Ljava/lang/String;)V", myJStringArg);

[explicit] QJniObject::QJniObject(jclass clazz, const char *signature, ...)

通过调用构造函数,并使用 `signature ` 指定后续所有参数的类型,从而基于 `clazz ` 构建一个新的 JNI 对象。

QJniEnvironment env;
jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
QJniObject(myClazz, "(I)V", 3);

[noexcept default] QJniObject::QJniObject(const QJniObject &other)

复制并构造一个QJniObject 实例。

[noexcept default] QJniObject::QJniObject(QJniObject &&other)

通过Move构造一个QJniObject 实例。

[noexcept] QJniObject::~QJniObject()

销毁 JNI 对象,并释放该 JNI 对象持有的所有引用。

[since 6.4] template <typename ReturnType = void, typename... Args> auto QJniObject::callMethod(const char *methodName, Args &&... args) const

调用方法 `methodName `,传入参数 `args `,并返回该值(除非 `Ret` 为 `void`)。如果 `Ret` 是 `jobject` 类型,则返回值将为 `QJniObject`。

QJniObject myJavaString("org/qtproject/qt/TestClass");
jint size = myJavaString.callMethod<jint>("length");

方法签名在编译时根据 Ret 以及args 的类型推导出来。Ret 可以是与std::expected 兼容且返回值的类型,也可以是被调用方法定义的any Java exception thrown 。

该函数在 Qt 6.4 中引入。

[since 6.4] template <typename ReturnType = void, typename... Args> auto QJniObject::callMethod(const char *methodName, const char *signature, Args &&... args) const

调用对象的methodName 方法,其中signature 用于指定后续参数args 的类型,并返回该值(除非Ret为void )。如果Ret是jobject类型,则返回值将是一个QJniObject 。

QJniObject myJavaString("org/qtproject/qt/TestClass");
jint index = myJavaString.callMethod<jint>("indexOf", "(I)I", 0x0051);

该函数在 Qt 6.4 中引入。

[since 6.4] template <typename Ret, typename... Args> QJniObject QJniObject::callObjectMethod(const char *methodName, Args &&... args) const

调用 Java 对象的 `methodName ` 方法,传入参数 `args `,并为返回的 Java 对象返回一个新的 `QJniObject `。

QJniObject myJavaString = QJniObject::fromString("Hello, Java");
QJniObject myJavaString2 = myJavaString1.callObjectMethod<jstring>("toString");

该方法的签名在编译时根据 Ret 以及args 的类型推导而出。Ret 可以是与std::expected 兼容且返回值的类型,也可以是被调用方法返回的any Java exception thrown 。

该函数在 Qt 6.4 中引入。

QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const

调用 Java 对象的 `methodName ` 方法,参数为 `signature `,其中 ` ` 指定后续所有参数的类型。

QJniObject myJavaString = QJniObject::fromString("Hello, Java");
QJniObject mySubstring = myJavaString.callObjectMethod("substring",
                                                       "(II)Ljava/lang/String;", 7, 11);

[static, since 6.7] template < typename Klass, typename ReturnType = void, typename... Args > auto QJniObject::callStaticMethod(const char *methodName, Args &&... args)

调用类Klass 上的静态方法methodName ,并返回类型为Ret的值(除非Ret是void )。如果Ret是jobject类型,则返回值将为QJniObject 。

该方法的签名在编译时根据 Ret 以及args 的类型推导出来。Klass 必须是一个具有已注册类型映射到 Java 类型的 C++ 类型。Ret 可以是与std::expected 兼容且会返回值的类型,也可以是被调用方法返回的any Java exception thrown 。

该函数在 Qt 6.7 中引入。

[static, since 6.4] template <typename ReturnType = void, typename... Args> auto QJniObject::callStaticMethod(const char *className, const char *methodName, Args &&... args)

调用类className 上的静态方法methodName ,传入参数args ,并返回类型为Ret的值(除非Ret是void )。如果Ret是jobject类型,则返回值将为QJniObject 。

jint value = QJniObject::callStaticMethod<jint>("MyClass", "staticMethod");

方法签名在编译时根据 Ret 以及args 的类型推导得出。Ret 可以是与std::expected 兼容且能返回值的类型,也可以是被调用方法的any Java exception thrown 。

该函数在 Qt 6.4 中引入。

[static, since 6.4] template <typename ReturnType = void, typename... Args> auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, Args &&... args)

调用clazz 上的静态方法methodName ,并返回类型为Ret的值(除非Ret是void )。如果Ret是jobject类型,则返回值将为QJniObject 。

QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jdouble randNr = QJniObject::callStaticMethod<jdouble>(javaMathClass, "random");

该方法的签名在编译时根据 Ret 以及args 的类型推导得出。Ret 可以是与std::expected 兼容且返回值的类型,也可以是被调用方法的any Java exception thrown 。

该函数在 Qt 6.4 中引入。

[static, since 6.4] template <typename ReturnType = void, typename... Args> auto QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, Args &&... args)

调用类clazz 中由methodId 标识的静态方法,并传入后续的任意参数,返回类型为Ret的值(除非Ret是void )。如果Ret是jobject类型,则返回值将为QJniObject 。

当clazz 和methodId 已从之前的操作中缓存下来时,此方法非常有用。

QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jmethodID methodId = env.findStaticMethod(javaMathClass, "max", "(II)I");
if (methodId != 0) {
    jint a = 2;
    jint b = 4;
    jint max = QJniObject::callStaticMethod<jint>(javaMathClass, methodId, a, b);
}

该函数在 Qt 6.4 中引入。

[static, since 6.4] template <typename Ret = void, typename... Args> auto QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&... args)

调用类className 中的静态方法methodName ,其中signature 用于指定后续所有参数args 的类型。返回该方法的结果(除非Ret为void )。如果Ret是jobject类型,则返回值将为QJniObject 。

jint a = 2;
jint b = 4;
jint max = QJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);

该函数在 Qt 6.4 中引入。

[static] template <typename Ret = void, typename... Args> auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&... args)

调用clazz 中的静态方法methodName ,其中signature 用于指定后续所有参数的类型。返回该方法的结果(除非Ret是void )。如果Ret是jobject类型,则返回值将为QJniObject 。

QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jint a = 2;
jint b = 4;
jint max = QJniObject::callStaticMethod<jint>(javaMathClass, "max", "(II)I", a, b);

[static, since 6.4] template <typename Ret, typename... Args> QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, Args &&... args)

调用类className 上的静态方法methodName ,传入参数args ,并为返回的Java对象返回一个新的QJniObject 。

QJniObject string = QJniObject::callStaticObjectMethod<jstring>("CustomClass", "getClassName");

该方法的签名在编译时根据 Ret 以及args 的类型推导得出。Ret 可以是与std::expected 兼容且返回值的类型,也可以是被调用方法的any Java exception thrown 。

该函数在 Qt 6.4 中引入。

[static, since 6.4] template <typename Ret, typename... Args> QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, Args &&... args)

调用静态方法,在clazz 上调用methodName ,传入参数args ,并为返回的Java对象返回一个新的QJniObject 。

该函数在 Qt 6.4 中引入。

[static] QJniObject QJniObject::callStaticObjectMethod(jclass clazz, jmethodID methodId, ...)

调用类clazz 中由methodId 标识的静态方法,并传入后续的任何参数。当clazz 和methodId 已从之前的操作中缓存时,此方法非常有用。

QJniEnvironment env;
jclass clazz = env.findClass("java/lang/String");
jmethodID methodId = env.findStaticMethod(clazz, "valueOf", "(I)Ljava/lang/String;");
if (methodId != 0)
    QJniObject str = QJniObject::callStaticObjectMethod(clazz, methodId, 10);

[static] QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...)

调用类className 中的静态方法methodName ,并使用signature 指定后续所有参数的类型。

QJniObject thread = QJniObject::callStaticObjectMethod("java/lang/Thread", "currentThread",
                                                       "()Ljava/lang/Thread;");
QJniObject string = QJniObject::callStaticObjectMethod("java/lang/String", "valueOf",
                                                       "(I)Ljava/lang/String;", 10);

[static] QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, const char *signature, ...)

调用类clazz 中的静态方法methodName ,并使用signature 指定后续所有参数的类型。

[since 6.2] QByteArray QJniObject::className() const

返回QJniObject 所持有的类对象的名称,该名称以QByteArray 的形式返回。

该函数在 Qt 6.2 中引入。

[static, since 6.4] template <typename Class, typename... Args> auto QJniObject::construct(Args &&... args)

构建一个与Class 等效的 Java 类实例,并返回一个包含该 JNI 对象的QJniObject 。args 中的参数将传递给 Java 构造函数。

QJniObject javaString = QJniObject::construct<jstring>();

只有当所有args 都是已知的JNI Types 时,此函数才可用。

该函数于 Qt 6.4 中引入。

[static] QJniObject QJniObject::fromLocalRef(jobject localRef)

根据本地 JNI 引用 `localRef` 创建一个 `QJniObject `。该函数会获取 `localRef ` 的所有权,并在返回前释放它。

注意:仅可 使用本地 JNI 引用调用此函数。例如,大多数通过 JNI 环境进行的原始 JNI 调用,都会返回指向 Java 对象的本地引用。

jobject localRef = env->GetObjectArrayElement(array, index);
QJniObject element = QJniObject::fromLocalRef(localRef);

[static] QJniObject QJniObject::fromString(const QString &string)

根据QString string 创建一个 Java 字符串,并返回一个包含该字符串的QJniObject 。

QString myQString = "QString";
QJniObject myJavaString = QJniObject::fromString(myQString);

另请参阅 toString()。

template <typename Type> auto QJniObject::getField(const char *fieldName) const

获取字段fieldName 的值。

QJniObject volumeControl("org/qtproject/qt/TestClass");
jint fieldValue = volumeControl.getField<jint>("FIELD_NAME");

template <typename T> QJniObject QJniObject::getObjectField(const char *fieldName) const

从字段fieldName 中获取一个 JNI 对象。

QJniObject field = jniObject.getObjectField<jstring>("FIELD_NAME");

QJniObject QJniObject::getObjectField(const char *fieldName, const char *signature) const

从字段fieldName 中通过signature 获取一个JNI对象。

注意:此 函数无需模板类型即可使用。

QJniObject field = jniObject.getObjectField("FIELD_NAME", "Ljava/lang/String;");

[static] template <typename Klass, typename T> auto QJniObject::getStaticField(const char *fieldName)

从类Klass 的静态字段fieldName 中检索值。

Klass 该值必须是一个 C++ 类型,且该类型已注册了映射到 Java 类型的映射。

[static] template <typename Type> auto QJniObject::getStaticField(const char *className, const char *fieldName)

从类className 的静态字段fieldName 中获取该值。

[static] template <typename Type> auto QJniObject::getStaticField(jclass clazz, const char *fieldName)

从clazz 上的静态字段 `fieldName ` 中获取该值。

[static] template <typename T> QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName)

从类className 的字段fieldName 中获取该对象。

QJniObject jobj = QJniObject::getStaticObjectField<jstring>("class/with/Fields", "FIELD_NAME");

[static] template <typename T> QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName)

从clazz 上的字段fieldName 中检索该对象。

QJniObject jobj = QJniObject::getStaticObjectField<jstring>(clazz, "FIELD_NAME");

[static] QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName, const char *signature)

从类className 的字段fieldName 中,通过signature 检索一个JNI对象。

注意:此 函数可不使用模板类型。

QJniObject jobj = QJniObject::getStaticObjectField("class/with/Fields", "FIELD_NAME",
                                                   "Ljava/lang/String;");

[static] QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName, const char *signature)

从类clazz 的字段fieldName 中,通过signature 检索一个JNI对象。

注意:此 函数无需模板类型即可使用。

QJniObject jobj = QJniObject::getStaticObjectField(clazz, "FIELD_NAME", "Ljava/lang/String;");

[static] bool QJniObject::isClassAvailable(const char *className)

如果 Java 类className 可用,则返回 true。

if (QJniObject::isClassAvailable("java/lang/String")) {
    // condition statement
}

bool QJniObject::isValid() const

如果该实例包含一个有效的 Java 对象,则返回 true。

QJniObject qjniObject;                        // ==> isValid() == false
QJniObject qjniObject(0)                      // ==> isValid() == false
QJniObject qjniObject("could/not/find/Class") // ==> isValid() == false

jobject QJniObject::object() const

template <typename T> T QJniObject::object() const

返回由QJniObject 持有的对象,形式可以是 jobject,也可以是类型 T。T 可以是以下类型之一:JNI Object Types 。

QJniObject string = QJniObject::fromString("Hello, JNI");
jstring jstring = string.object<jstring>();

注意:该 QJniObject 仍会保留所 返回对象 的生命周期。若要使该对象的生命周期超出此QJniObject 的存续时间(例如,为日后使用而进行记录),最简单的方法是将其存储在另一个具有适当生命周期的QJniObject 中。此外,您也可以为该对象创建一个新的全局引用并进行存储,但请务必在使用完毕后将其释放。

void functionScope()
{
    QString helloString("Hello");
    jstring myJString = 0;
    {
        QJniObject string = QJniObject::fromString(helloString);
        myJString = string.object<jstring>();
    }

    // Ops! myJString is no longer valid.
    QString myQtString = QJniObject(myJString).toString();
}

[since 6.2] jclass QJniObject::objectClass() const

将QJniObject 所持有的类对象作为jclass 返回。

注意:该 QJniObject 仍会保留返回对象 的生命周期。若要使该对象的生命周期超出此QJniObject 的范围(例如,将其记录下来以备后用),最简单的方法是将其存储在另一个具有适当生命周期的QJniObject 中。或者,您可以为该对象创建一个新的全局引用并将其存储起来,但请注意,在使用完毕后务必将其释放。

该函数在 Qt 6.2 中引入。

template <typename Ret = void, typename Type> auto QJniObject::setField(const char *fieldName, Type value)

将fieldName 的值设置为value 。

QJniObject obj;
obj.setField<jint>("AN_INT_FIELD", 10);
jstring myString = ...;
obj.setField<jstring>("A_STRING_FIELD", myString);

template <typename Ret = void, typename Type> auto QJniObject::setField(const char *fieldName, const char *signature, Type value)

将fieldName 的值通过signature 设置为value 。

QJniObject stringArray = ...;
QJniObject obj = ...;
obj.setObjectField<jobjectArray>("KEY_VALUES", "([Ljava/lang/String;)V",
                           stringArray.object<jobjectArray>())

[static] template < typename Klass, typename Ret = void, typename Type > auto QJniObject::setStaticField(const char *fieldName, Type value)

将类Klass 的静态字段fieldName 设置为value 。

Klass 该类型必须是 C++ 类型,且具有已注册的类型映射,映射到 Java 类型。

[static] template <typename Ret = void, typename Type> auto QJniObject::setStaticField(const char *className, const char *fieldName, Type value)

将类className 的静态字段fieldName 设置为value 。

[static] template <typename Ret = void, typename Type> auto QJniObject::setStaticField(jclass clazz, const char *fieldName, Type value)

将类clazz 的静态字段fieldName 设置为value 。

[static] template <typename Ret = void, typename Type> auto QJniObject::setStaticField(const char *className, const char *fieldName, const char *signature, Type value)

使用设置器(参数为signature ),将类className 的静态字段fieldName 设置为value 。

[static] template <typename Ret = void, typename Type> auto QJniObject::setStaticField(jclass clazz, const char *fieldName, const char *signature, Type value)

使用signature 调用设置器,将类clazz 的静态字段fieldName 设置为value 。

[noexcept, since 6.8] void QJniObject::swap(QJniObject &other)

将该对象与other 互换。此操作速度极快,且绝不会失败。

该函数于 Qt 6.8 中引入。

QString QJniObject::toString() const

返回一个包含该 Java 对象字符串表示形式的 `QString `。对 Java `String` 对象调用此函数是获取其实际字符串数据的一种便捷方式。

QJniObject string = ...; //  "Hello Java"
QString qstring = string.toString(); // "Hello Java"

另请参阅 fromString()。

[noexcept default] QJniObject &QJniObject::operator=(QJniObject &&other)

将other 通过Move操作赋值给此QJniObject 实例。

template <typename T, std::enable_if_t<std::is_convertible_v<T, jobject>, bool> = true> QJniObject &QJniObject::operator=(T object)

将当前对象替换为object 。旧的 Java 对象将被释放。

[noexcept default] QJniObject &QJniObject::operator=(const QJniObject &other)

将other 复制并赋值给此QJniObject 实例。

相关的非成员

bool operator!=(const QJniObject &o1, const QJniObject &o2)

如果 `o1 ` 引用的对象与 `o2` 引用的对象不同,则返回 true。

bool operator==(const QJniObject &o1, const QJniObject &o2)

如果两个对象o1 和o2 都引用同一个Java对象,或者两者均为NULL,则返回true;在其他任何情况下,将返回false。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.