Revision control
Copy as Markdown
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QJniArrayBase
\brief The QJniArrayBase class provides common, type-independent APIs for QJniArray.
\inmodule QtCore
\ingroup frameworks-technologies
\since 6.8
*/
/*!
\typedef QJniArrayBase::size_type
A 32 bit integer.
*/
/*!
\fn template <typename Container, QJniArrayBase::if_compatible_source_container<Container>> auto QJniArrayBase::fromContainer(Container &&container)
Creates a Java array holding the data in \a container, and returns a
QJniArray instance that wraps it.
//! [forward-iterable-containers]
\constraints \c{Container}
is a container that stores elements of a \l{JNI types}{JNI type} or equivalent
C++ type, and provides a forward iterator.
The specialization of the constructed QJniArray depends on the value type
of the \a container. For a \c{Container<T>} (such as e.g. \c{QList<T>}) it
will typically be \c{QJniArray<T>}, with the following exceptions:
\table
\header
\li Container
\li Specialization
\row
\li QByteArray
\li QJniArray<jbyte>
\row
\li QStringList
\li QJniArray<jstring>
\header
\li Container::value_type
\li Specialization
\row
\li QJniObject
\li QJniArray<jobject>
\endtable
//! [forward-iterable-containers]
\sa QJniArray::toContainer()
*/
/*!
\fn QJniArrayBase::operator QJniObject() const
\return a QJniObject wrapping the same \c{jobject} as this QJniArray instance.
*/
/*!
\fn void QJniArrayBase::swap(QJniArrayBase &other)
\memberswap{array object}
*/
/*!
\fn template <typename T> T QJniArrayBase::object() const
\return the object held by the QJniArray as type T, which can be one of the
\l {QJniObject#Object Types}{JNI Object Types}.
*/
/*!
\fn bool QJniArrayBase::isValid() const
\return whether the QJniArray object wraps a valid `jobject`. For invalid
QJniArray instances, object() returns \nullptr. Iterating over an invalid
object is safe (begin() will return the same as end()), and calling
\l{QJniArray::}{toContainer()} on an invalid array will return an empty
container.
\sa QJniObject::isValid(), object(), QJniArray::toContainer()
*/
/*!
\fn bool QJniArrayBase::isEmpty() const
\return \c true if the array has size 0; otherwise returns \c false.
An \l{isValid}{invalid} array is always empty.
\c isValid(), size()
*/
/*!
\fn QJniArrayBase::size_type QJniArrayBase::size() const
\return the size of the array.
*/
/*!
\class QJniArray
\brief The QJniArray class is a template class that represents an array in Java.
\inmodule QtCore
\ingroup frameworks-technologies
\since 6.8
QJniArray is a template class where \a T specifies the element type of the
Java array. The type can be a JNI primitive type such as \c jint or \c jbyte,
or an object type such as \c jobject, \c jstring, or a type declared with
Q_DECLARE_JNI_CLASS.
The QJniArray template makes it easy to work with Java methods that return
or take a Java array.
\note \l{Java arrays} can hold primitive types and objects. The array
itself can be treated like a Java Object, and the JNI framework provides
explicit APIs to work with such arrays. In addition, the Java class library
provides container types such as \c{List} or \c{ArrayList}. Objects of
those types can not be represented by a QJniArray. Instead, use QJniObject
to call the class-specific member functions.
To create a QJniArray instance, either construct it from a corresponding C++
container:
\code
QList<int> intList;
const QJniArray intArray = QJniArray(intList);
\endcode
or from an initializer list:
\code
const QJniArray intArray{1, 2, 3};
\endcode
QJniArray will create a new Java array and copy the C++-side data into it.
When calling functions that return an array via QJniObject::callMethod,
such as \c{char[] toCharArray()} in the Java \c{String} class, specify the
return type as a C array (\c{jchar[]} in the following):
\code
const auto charArray = stringObject.callMethod<jchar[]>("toCharArray");
\endcode
The \c{charArray} variable will be of type \c{QJniArray<jchar>}, and hold
a new global reference to the \c{jcharArray} JNI object.
Note that the arrays in the code snippets above are all const. Accessing
elements in a const array is considerably more efficient than operating on
a mutable array.
A QJniArray can also be constructed from an existing \c{jarray} or
QJniObject. However, note that no type checking is performed to verify that
the \c{jarray} or QJniObject indeed represents an array holding elements of
the specified type, and accessing a mismatching QJniArray results in
undefined behavior.
The data in a QJniArray can either be accessed element by element using
at() or \l{QJniArray::}{operator[]()}, or iterated over.
\code
for (const auto &value : array)
process(value);
\endcode
To copy the entire array into a C++ side Qt container, use the toContainer()
function.
\code
const auto bytes = object.callMethod<jbyte[]>("getBytes");
QByteArray data = bytes.toContainer();
\endcode
which happens implicitly in
\code
const auto data = object.callMethod<QByteArray>("getBytes");
\endcode
The return type of toContainer() depends on the type that QJniArray has
been instantiated with.
//! [type-mapping]
For \c{QJniArray<T>} this will typically be \c{QList<T>}, with the
following exceptions:
\table
\header
\li Specialization
\li C++ type
\row
\li QJniArray<jbyte>
\li QByteArray
\row
\li QJniArray<char>
\li QByteArray
\row
\li QJniArray<jstring>
\li QStringList
\row
\li QJniArray<QString>
\li QStringList
\endtable
//! [type-mapping]
An array of a fixed size can also be created without any data, and can then
be populated element by element using
\l{QJniArray::operator[]()}{operator[]}:
\code
QJniArray<jint> intArray(size);
for (int i = 0; i < size; ++i)
intArray[i] = i;
\endcode
or a mutable iterator:
\code
QJniArray<QString> strings(size);
int i = 0;
for (auto string : strings) // note: not 'auto &string'
string = u"Row %1"_s.arg(i++);
\endcode
As in Java, the size of an array can not be changed, but the array variable
can be assigned to a different array.
\note Java arrays are limited to 32 bits, and the \c{size_type} member type of
QJniArray is \c{jsize}, which is a 32bit integer type. Trying to construct
a QJniArray from a C++ container that holds more than 2^32 elements will
cause a runtime assertion.
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray()
Default constructor of QJniArray. This does not create a Java-side array,
and the instance will be invalid.
\sa isValid
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray(jarray array)
Constructs a QJniArray that wraps the Java-side array \a array,
creating a new global reference to \a array.
//! [no-array-validation]
\note This constructor does not perform any validation of whether the
Java-side object is an array of the correct type. Accessing a
mismatching QJniArray results in undefined behavior.
//! [no-array-validation]
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray(const QJniObject &object)
Constructs a QJniArray that wraps the same Java array as \a object,
creating a new global reference. To construct a QJniArray from an existing
local reference, use a QJniObject constructed via
\l{QJniObject::}{fromLocalRef()}.
\include qjniarray.qdoc no-array-validation
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray(QJniObject &&object)
Constructs a QJniArray by moving from \a object. The QJniObject becomes
\l{QJniObject::isValid}{invalid}.
\include qjniarray.qdoc no-array-validation
*/
/*!
\fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray<T>::QJniArray(const QJniArray<Other> &other)
Constructs a QJniArray by copying \a other. Both QJniArray objects will
reference the same Java array object.
\constraints the element
type \c{Other} of \a other is convertible to the element type \c{T} of the
QJniArray being constructed. However, no actual conversion takes place.
*/
/*!
\fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray<T>::QJniArray(QJniArray<Other> &&other)
Constructs a QJniArray by moving from \a other. The \a other array becomes
\l{QJniArrayBase::isValid}{invalid}.
\constraints the element
type \c{Other} of \a other is convertible to the element type \c{T} of the
QJniArray being constructed. However, no actual conversion takes place.
*/
/*!
\fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray &QJniArray<T>::operator=(const QJniArray<Other> &other)
Assigns \a other to this QJniArray, and returns a reference to this. Both
QJniArray objects will reference the same Java array object.
\constraints the element
type \c{Other} of \a other is convertible to the element type \c{T} of this
QJniArray. However, no actual conversion takes place.
*/
/*!
\fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray &QJniArray<T>::operator=(QJniArray<Other> &&other)
Moves \a other into this QJniArray, and returns a reference to this. The
\a other array becomes \l{QJniArrayBase::isValid}{invalid}.
\constraints the element
type \c{Other} of \a other is convertible to the element type \c{T} of this
QJniArray. However, no actual conversion takes place.
*/
/*!
\fn template <typename T> template <typename Container, QJniArrayBase::if_compatible_source_container<Container>> QJniArray<T>::QJniArray(Container &&container)
Constructs a QJniArray that wraps a newly-created Java array for elements of
type \c{Container::value_type}, and populates the Java array with the data from
\a container.
\include qjniarray.qdoc forward-iterable-containers
\sa QJniArrayBase::fromContainer(), toContainer()
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray(std::initializer_list<T> &list)
Constructs a QJniArray that wraps a newly-created Java array for elements of
type \c{T}, and populates the Java array with the data from \a list.
\sa QJniArrayBase::fromContainer(), toContainer()
*/
/*!
\fn template <typename T> QJniArray<T>::QJniArray(size_type size)
\since 6.9
Constructs an empty QJniArray of size \a size. The elements in the array do
not get initialized.
*/
/*!
\fn template <typename T> QJniArray<T>::~QJniArray()
Destroys the QJniArray object and releases any references held to the
wrapped Java array.
*/
/*!
\fn template <typename T> auto QJniArray<T>::arrayObject() const
\return the wrapped Java object as the suitable \c{jarray} type that
matches the element type \c{T} of this QJniArray object.
\table
\header
\li T
\li jarray type
\row
\li jbyte
\li jbyteArray
\row
\li jchar
\li jcharArray
\row
\li ...
\li ...
\row
\li jobject
\li jobjectArray
\row
\li QJniObject
\li jobjectArray
\row
\li Q_DECLARE_JNI_CLASS
\li jobjectArray
\endtable
*/
/*!
\typedef QJniArray::iterator
A random-access iterator for QJniArray.
/*
/*!
\typedef QJniArray::const_iterator
A random-access, const iterator for QJniArray.
*/
/*!
\typedef QJniArray::reverse_iterator
A reverse iterator for QJniArray, synonym for
\c{std::reverse_iterator<iterator>}.
//! [reverse_iterator-operator->]
\note Accessing the element of the reverse iterator using \c{operator->()}
requires C++20, as the C++17 reverse_iterator does not support iterators that
return a proxy object.
//! [reverse_iterator-operator->]
/*
/*!
\typedef QJniArray::const_reverse_iterator
A reverse iterator for the QJniArray, synonym for
\c{std::reverse_iterator<const_iterator>}.
\include qjniarray.qdoc reverse_iterator-operator->
*/
/*!
\fn template <typename T> const_iterator QJniArray<T>::begin() const
\fn template <typename T> iterator QJniArray<T>::begin()
\fn template <typename T> const_iterator QJniArray<T>::constBegin() const
\fn template <typename T> const_iterator QJniArray<T>::cbegin() const
Returns an \l{STL-style iterators}{STL-style const iterator} pointing to the
first item in the array.
If the array is \l{QJniArrayBase::isValid()}{invalid}, then this will return
the same iterator as the corresponding end() function.
\sa end(), rbegin()
*/
/*!
\fn template <typename T> const_iterator QJniArray<T>::end() const
\fn template <typename T> iterator QJniArray<T>::end()
\fn template <typename T> const_iterator QJniArray<T>::constEnd() const
\fn template <typename T> const_iterator QJniArray<T>::cend() const
Returns an \l{STL-style iterators}{STL-style iterator} pointing just
after the last item in the list.
\sa begin(), rend()
*/
/*!
\fn template <typename T> const_reverse_iterator QJniArray<T>::rbegin() const
\fn template <typename T> reverse_iterator QJniArray<T>::rbegin()
\fn template <typename T> const_reverse_iterator QJniArray<T>::crbegin() const
Returns an \l{STL-style iterators}{STL-style reverse iterator} pointing to
the first item in the array, in reverse order.
If the array is \l{QJniArrayBase::isValid()}{invalid}, then this will return
the same iterator as the corresponding rend() function.
\include qjniarray.qdoc reverse_iterator-operator->
\sa rend(), begin()
*/
/*!
\fn template <typename T> const_reverse_iterator QJniArray<T>::rend() const
\fn template <typename T> reverse_iterator QJniArray<T>::rend()
\fn template <typename T> const_reverse_iterator QJniArray<T>::crend() const
Returns an \l{STL-style iterators}{STL-style reverse iterator} pointing just
after the last item in the list, in reverse order.
\include qjniarray.qdoc reverse_iterator-operator->
\sa rbegin(), end()
*/
/*!
\fn template <typename T> T QJniArray<T>::operator[](size_type i) const
\fn template <typename T> T QJniArray<T>::at(size_type i) const
Returns the value at position \a i in the wrapped Java array.
\a i must be a valid index position in the list (i.e.,
0 <= \a i < size()).
\sa size()
*/
/*!
\fn template <typename T> QJniArray<T>::reference QJniArray<T>::operator[](size_type i)
\since 6.9
Returns a reference object for value at position \a i in the wrapped Java
array.
\a i must be a valid index position in the list (i.e., 0 <= \a i < size()).
The returned reference object holds the value at position \a i, and in most
cases will convert implicitly to the value. Assigning to the returned
reference will overwrite the entry in the Java array. However, calling
mutating member functions on the object will not modify the entry in the
array. To call member function on the result of this operator, dereference
the reference object:
\code
QJniArray<QString> strings = object.callMethod<QString[]>("getStrings");
if (!strings.isEmpty()) {
if (!(*array[0]).isEmpty()) {
// ...
}
}
\endcode
However, if modifying the value in the array itself is not intended, make
the array const, or use \l{at()} instead.
\sa at(), size()
*/
/*!
\fn template <typename T> template <typename Container, QJniArrayBase::if_compatible_target_container<T, Container>> Container QJniArray<T>::toContainer(Container &&container) const
\return a container populated with the data in the wrapped Java array.
If no \a container is provided, then the type of the container returned
depends on the element type of this QJniArray.
\include qjniarray.qdoc type-mapping
If you pass in a named container (an lvalue) for \a container, then that
container is filled, and a reference to it is returned. If you pass in a
temporary container (an rvalue, incl. the default argument), then that
container is filled, and returned by value.
This function returns immediately if the array is
\l{QJniArrayBase::isValid()}{invalid}.
\sa QJniArrayBase::fromContainer()
*/