Vous êtes sur la page 1sur 23

17/06/2021 Calling Java from Kotlin | Kotlin

Regardez l'enregistrement de l'événement Kotlin 1.5 !


v1.5.10 Solutions Documents Communauté Apprendre Jouer

Appeler Java depuis Kotlin


Modifier la page Dernière modification : 03 juin 2021

Kotlin est conçu avec l'interopérabilité Java à l'esprit. Le code Java existant peut être appelé à partir
de Kotlin de manière naturelle, et le code Kotlin peut également être utilisé à partir de Java de
manière assez fluide. Dans cette section, nous décrivons quelques détails sur l'appel de code Java à
partir de Kotlin.

Pratiquement tout le code Java peut être utilisé sans aucun problème :

import java.util.*

fun demo(source: List<Int>) {


val list = ArrayList<Int>()
// 'for'-loops work for Java collections:
for (item in source) {
list.add(item)
}
// Operator conventions work as well:
for (i in 0..source.size - 1) {
list[i] = source[i] // get and set are called
}
}

Getters et setters
Les méthodes qui suivent les conventions Java pour les getters et setters (méthodes sans argument
avec des noms commençant par get et méthodes à argument unique avec des noms commençant

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 1/23
17/06/2021 Calling Java from Kotlin | Kotlin

par set ) sont représentées en tant que propriétés dans Kotlin. Boolean Les méthodes d'accès
(où le nom du getter commence par is et le nom du setter commence par set ) sont
représentées comme des propriétés qui ont le même nom que la méthode getter.

import java.util.Calendar

fun calendarDemo() {
val calendar = Calendar.getInstance()
if (calendar.firstDayOfWeek == Calendar.SUNDAY) { // call getFirst
calendar.firstDayOfWeek = Calendar.MONDAY // call setFirstDayOf
}
if (!calendar.isLenient) { // call isLenient()
calendar.isLenient = true // call setLenient()
}
}

Notez que, si la classe Java n'a qu'un setter, il n'est pas visible en tant que propriété dans Kotlin car
Kotlin ne prend pas en charge les propriétés set-only.

Méthodes retournant void


Si une méthode Java retourne void , elle retournera Unit lorsqu'elle sera appelée depuis Kotlin.
Si par hasard quelqu'un utilise cette valeur de retour, elle sera attribuée au site d'appel par le
compilateur Kotlin puisque la valeur elle-même est connue à l'avance (étant Unit ).

Échappement pour les identifiants Java qui


sont des mots-clés dans Kotlin
Certains des mots-clés de Kotlin sont des identifiants valides en Java : in , object , is , et
autres. Si une bibliothèque Java utilise un mot-clé Kotlin pour une méthode, vous pouvez toujours
appeler la méthode en l'échappant avec le caractère backtick (`) :

foo.`is`(bar)

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 2/23
17/06/2021 Calling Java from Kotlin | Kotlin

Types de plate-forme et de sécurité nulle


Toute référence en Java peut être null , ce qui rend les exigences de sécurité nulle strictes de
Kotlin peu pratiques pour les objets provenant de Java. Les types de déclarations Java sont traités
dans Kotlin d'une manière spécifique et appelés types de plate-forme . Les vérifications nulles sont
assouplies pour ces types, de sorte que les garanties de sécurité pour eux sont les mêmes qu'en
Java (voir plus ci-dessous ).

Considérez les exemples suivants :

val list = ArrayList<String>() // non-null (constructor result)


list.add("Item")
val size = list.size // non-null (primitive int)
val item = list[0] // platform type inferred (ordinary Java object)

Lorsque vous appelez des méthodes sur des variables de types de plate-forme, Kotlin n'émet pas
d'erreurs de nullabilité au moment de la compilation, mais l'appel peut échouer au moment de
l'exécution, en raison d'une exception de pointeur null ou d'une assertion que Kotlin génère pour
empêcher la propagation des nulls :

item.substring(1) // allowed, may throw an exception if item == null

Les types de plate-forme ne sont pas dénotables , ce qui signifie que vous ne pouvez pas les écrire
explicitement dans le langage. Lorsqu'une valeur de plate-forme est attribuée à une variable Kotlin,
vous pouvez vous fier à l'inférence de type (la variable aura alors un type de plate-forme inféré,
comme item dans l'exemple ci-dessus), ou vous pouvez choisir le type que vous attendez (nullable
et non -les types nuls sont autorisés) :

val nullable: String? = item // allowed, always works


val notNull: String = item // allowed, may fail at runtime

Si vous choisissez un type non nul, le compilateur émettra une assertion lors de l'affectation. Cela
empêche les variables non nulles de Kotlin de contenir des valeurs nulles. Des assertions sont
également émises lorsque vous transmettez des valeurs de plate-forme aux fonctions Kotlin en
attendant des valeurs non nulles et dans d'autres cas. Dans l'ensemble, le compilateur fait de son

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 3/23
17/06/2021 Calling Java from Kotlin | Kotlin

mieux pour empêcher les nulls de se propager loin dans le programme bien que parfois cela soit
impossible à éliminer entièrement, à cause des génériques.

Notation pour les types de plate-forme


Comme mentionné ci-dessus, les types de plate-forme ne peuvent pas être mentionnés
explicitement dans le programme, il n'y a donc pas de syntaxe pour eux dans le langage.
Néanmoins, le compilateur et l'IDE doivent parfois les afficher (par exemple, dans les messages
d'erreur ou les informations sur les paramètres), il existe donc une notation mnémonique pour eux :

• T! signifie " T ou T? ",

• (Mutable)Collection<T>! signifie "La collection Java de T peut être modifiable ou non,


peut être nullable ou non",

• Array<(out) T>! signifie "tableau Java de T (ou un sous-type de T ), nullable ou non"

Annotations de nullité
Les types Java qui ont des annotations de nullité ne sont pas représentés comme des types de
plate-forme, mais comme des types Kotlin nullables ou non null. Le compilateur prend en charge
plusieurs types d'annotations de nullabilité, notamment :

• JetBrains ↗ ( @Nullable et @NotNull du org.jetbrains.annotations package)

• Android ( com.android.annotations et android.support.annotations )

• JSR-305 ( javax.annotation , plus de détails ci-dessous)

• Trouver des bogues ( edu.umd.cs.findbugs.annotations )

• Éclipse ( org.eclipse.jdt.annotation )

• Lombok ( lombok.NonNull )

Vous pouvez trouver la liste complète dans le code source du compilateur Kotlin ↗ .

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 4/23
17/06/2021 Calling Java from Kotlin | Kotlin

Annotation des arguments de type et des paramètres


de type
Vous pouvez annoter les arguments de type et les paramètres de type des types génériques pour
leur fournir également des informations de nullité.

Tous les exemples de la section utilisent les annotations de nullabilité JetBrains du


org.jetbrains.annotations package.

Tapez les arguments


Considérez ces annotations sur une déclaration Java :

@NotNull
Set<@NotNull String> toSet(@NotNull Collection<@NotNull String> element

Ils se traduisent par la signature suivante en Kotlin :

fun toSet(elements: (Mutable)Collection<String>) : (Mutable)Set<String

Lorsque l' @NotNull annotation est manquante dans un argument de type, vous obtenez un type
de plate-forme à la place :

fun toSet(elements: (Mutable)Collection<String!>) : (Mutable)Set<Strin

Paramètres de type
Par défaut, la possibilité de nullité des paramètres de type simple dans Kotlin et Java n'est pas
définie. En Java, vous pouvez le spécifier à l'aide d'annotations de nullabilité. Annotons le paramètre
type de la Base classe :

public class Base<@NotNull T> {}

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 5/23
17/06/2021 Calling Java from Kotlin | Kotlin

Lors de l'héritage de Base , Kotlin attend un argument de type ou un paramètre de type non
nullable. Ainsi, le code Kotlin suivant produit un avertissement :

class Derived<K> : Base<K> {} // warning: K has undefined nullability

Vous pouvez le corriger en spécifiant la limite supérieure K : Any .

Kotlin prend également en charge les annotations de nullabilité sur les limites des paramètres de
type Java. Ajoutons des limites à Base :

public class BaseWithBound<T extends @NotNull Number> {}

Kotlin traduit cela comme suit :

class BaseWithBound<T : Number> {}

Donc, passer un type nullable en tant qu'argument de type ou paramètre de type produit un
avertissement.

L'annotation des arguments de type et des paramètres de type fonctionne avec la cible Java 8 ou
supérieure. La fonctionnalité nécessite que les annotations de nullabilité prennent en charge la
TYPE_USE cible ( org.jetbrains.annotations prend en charge cela dans les versions 15 et
supérieures). Passez l' -Xtype-enhancement-improvements-strict-mode option du compilateur
pour signaler les erreurs dans le code Kotlin qui utilise la nullité qui s'écarte des annotations de
nullité de Java.

Remarque : si une annotation de nullité prend en charge d'autres cibles applicables à un


type en plus de la TYPE_USE cible, alors TYPE_USE a la priorité. Par exemple, si
@Nullable a à la fois TYPE_USE et des METHOD cibles, la signature de la méthode Java
@Nullable String[] f() devient fun f(): Array<String?>! en Kotlin.

Prise en charge de JSR-305

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 6/23
17/06/2021 Calling Java from Kotlin | Kotlin

L' @Nonnull ↗annotation définie dans JSR-305 ↗ est prise en charge pour indiquer la nullité des
types Java.

Si la @Nonnull(when = ...) valeur est When.ALWAYS , le type annoté est traité comme non nul ;
When.MAYBE et When.NEVER dénotent un type nullable ; et When.UNKNOWN force le type à être la
plate-forme un .

Une bibliothèque peut être compilée avec les annotations JSR-305, mais il n'est pas nécessaire de
faire de l'artefact d'annotations (par exemple jsr305.jar ) une dépendance de compilation pour
les consommateurs de la bibliothèque. Le compilateur Kotlin peut lire les annotations JSR-305 à
partir d'une bibliothèque sans les annotations présentes sur le chemin de classe.

Les qualificatifs de nullabilité personnalisés (KEEP-79) ↗ sont également pris en charge (voir ci-
dessous).

Tapez les surnoms qualificatifs


Si un type d'annotation est annoté à la fois avec @TypeQualifierNickname ↗et JSR-305
@Nonnull (ou son autre surnom, tel que @CheckForNull ), alors le type d'annotation est lui-
même utilisé pour récupérer la nullabilité précise et a la même signification que cette annotation de
nullabilité :

@TypeQualifierNickname
@Nonnull(when = When.ALWAYS)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyNonnull {
}

@TypeQualifierNickname
@CheckForNull // a nickname to another type qualifier nickname
@Retention(RetentionPolicy.RUNTIME)
public @interface MyNullable {
}

interface A {
@MyNullable String foo(@MyNonnull String x);
// in Kotlin (strict mode): `fun foo(x: String): String?`

String bar(List<@MyNonnull String> x);

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 7/23
17/06/2021 Calling Java from Kotlin | Kotlin

// in Kotlin (strict mode): `fun bar(x: List<String>!): String!`


}

Type de qualificateur par défaut


@TypeQualifierDefault ↗ permet d'introduire des annotations qui, lorsqu'elles sont appliquées,
définissent la nullabilité par défaut dans la portée de l'élément annoté.

Un tel type d'annotation doit lui-même être annoté à la fois @Nonnull (ou son surnom) et
@TypeQualifierDefault(...) avec une ou plusieurs ElementType valeurs :

• ElementType.METHOD pour les types de retour de méthodes

• ElementType.PARAMETER pour les paramètres de valeur

• ElementType.FIELD pour les champs

• ElementType.TYPE_USE pour tout type, y compris les arguments de type, les limites
supérieures des paramètres de type et les types génériques

La nullabilité par défaut est utilisée lorsqu'un type lui-même n'est pas annoté par une annotation de
nullabilité, et la valeur par défaut est déterminée par l'élément englobant le plus interne annoté
avec une annotation par défaut de qualificateur de type ElementType correspondant à l'utilisation
du type.

@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}

@Nonnull(when = When.MAYBE)
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, Elem
public @interface NullableApi {
}

@NullableApi
interface A {
String foo(String x); // fun foo(x: String?): String?

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 8/23
17/06/2021 Calling Java from Kotlin | Kotlin

@NotNullApi // overriding default from the interface


String bar(String x, @Nullable String y); // fun bar(x: String, y:

// The List<String> type argument is seen as nullable because of `@


// having the `TYPE_USE` element type:
String baz(List<String> x); // fun baz(List<String?>?): String?

// The type of `x` parameter remains platform because there's an ex


// UNKNOWN-marked nullability annotation:
String qux(@Nonnull(when = When.UNKNOWN) String x); // fun baz(x:
}

Les types dans cet exemple n'ont lieu qu'avec le mode strict activé ; sinon, les types de
plate-forme restent. Voir les sections d' @UnderMigration annotation et de
configuration du compilateur .

La nullabilité par défaut au niveau du package est également prise en charge :

// FILE: test/package-info.java
@NonNullApi // declaring all types in package 'test' as non-nullable by
package test;

Annotation @UnderMigration
L' @UnderMigration annotation (fournie dans un artefact séparé kotlin-annotations-jvm )
peut être utilisée par les responsables de la bibliothèque pour définir le statut de migration pour les
qualificatifs de type de nullabilité.

La valeur d'état dans @UnderMigration(status = ...) spécifie comment le compilateur traite


les utilisations inappropriées des types annotés dans Kotlin (par exemple, en utilisant une
@MyNullable valeur de type -annotée comme non nulle) :

• MigrationStatus.STRICT fait fonctionner l'annotation comme n'importe quelle annotation


de nullabilité simple, c'est-à-dire signaler les erreurs pour les utilisations inappropriées et
affecter les types dans les déclarations annotées telles qu'elles sont vues dans Kotlin

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 9/23
17/06/2021 Calling Java from Kotlin | Kotlin

• MigrationStatus.WARN : les utilisations inappropriées sont signalées comme des


avertissements de compilation au lieu d'erreurs, mais les types dans les déclarations annotées
restent plate-forme

• MigrationStatus.IGNORE fait que le compilateur ignore complètement l'annotation de


nullabilité

Un responsable de bibliothèque peut ajouter un @UnderMigration statut à la fois aux surnoms et


aux valeurs par défaut des qualificatifs de type :

@Nonnull(when = When.ALWAYS)
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
@UnderMigration(status = MigrationStatus.WARN)
public @interface NonNullApi {
}

// The types in the class are non-null, but only warnings are reported
// because `@NonNullApi` is annotated `@UnderMigration(status = Migrat
@NonNullApi
public class Test {}

L'état de migration d'une annotation de nullité n'est pas hérité par ses surnoms de
qualificatif de type mais est appliqué à ses utilisations dans les qualificatifs de type par
défaut.

Si un qualificatif de type par défaut utilise un pseudonyme de qualificatif de type et qu'ils sont tous
les deux @UnderMigration , le statut du qualificatif de type par défaut est utilisé.

Configuration du compilateur
Les contrôles JSR-305 peuvent être configurés en ajoutant le -Xjsr305 drapeau du compilateur
avec les options suivantes (et leur combinaison) :

• -Xjsr305={strict|warn|ignore} pour configurer le comportement pour les non-


@UnderMigration annotations. Les qualificatifs de nullabilité personnalisés, en particulier
@TypeQualifierDefault , sont déjà répandus dans de nombreuses bibliothèques bien
connues, et les utilisateurs peuvent avoir besoin de migrer en douceur lors de la mise à jour vers

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 10/23
17/06/2021 Calling Java from Kotlin | Kotlin

la version Kotlin contenant la prise en charge de JSR-305. Depuis Kotlin 1.1.60, ce drapeau
n'affecte que les non- @UnderMigration annotations.

• -Xjsr305=under-migration:{strict|warn|ignore} pour remplacer le comportement des


@UnderMigration annotations. Les utilisateurs peuvent avoir une vision différente du statut de
migration pour les bibliothèques : ils peuvent souhaiter avoir des erreurs alors que le statut de
migration officiel est WARN , ou vice versa, ils peuvent souhaiter reporter le signalement
d'erreurs pour certaines jusqu'à ce qu'ils terminent leur migration.

• -Xjsr305=@<fq.name>:{strict|warn|ignore} pour remplacer le comportement d'une


seule annotation, où <fq.name> est le nom de classe complet de l'annotation. Peut apparaître
plusieurs fois pour différentes annotations. Ceci est utile pour gérer l'état de la migration pour
une bibliothèque particulière.

Les valeurs strict , warn et ignore ont la même signification que celles de
MigrationStatus , et seul le strict mode affecte les types dans les déclarations annotées telles
qu'elles sont vues dans Kotlin.

Note: le haut-JSR-305 annotations @Nonnull ↗, @Nullable ↗et @CheckForNull


↗sont toujours activées et affectent les types de déclarations annotés dans Kotlin, quelle
que soit la configuration du compilateur avec le -Xjsr305 drapeau.

Par exemple, l'ajout


-Xjsr305=ignore -Xjsr305=under-migration:ignore -
Xjsr305=@org.library.MyNullable:warn
d'arguments au compilateur oblige le compilateur à générer des avertissements pour les utilisations
inappropriées des types annotés par @org.library.MyNullable et à ignorer toutes les autres
annotations JSR-305.

Le comportement par défaut est le même pour -Xjsr305=warn . La strict valeur doit être
considérée comme expérimentale (d'autres vérifications pourraient y être ajoutées à l'avenir).

Types mappés
Kotlin traite spécifiquement certains types Java. De tels types ne sont pas chargés à partir de Java
"en l'état", mais sont mappés aux types Kotlin correspondants. Le mappage n'a d'importance qu'au

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 11/23
17/06/2021 Calling Java from Kotlin | Kotlin

moment de la compilation, la représentation à l'exécution reste inchangée. Les types primitifs de


Java sont mappés aux types Kotlin correspondants (en gardant à l'esprit les types de plate-forme ) :

type Java Type Kotlin

byte kotlin.Byte

short kotlin.Short

int kotlin.Int

long kotlin.Long

char kotlin.Char

float kotlin.Float

double kotlin.Double

boolean kotlin.Boolean

Certaines classes intégrées non primitives sont également mappées :

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 12/23
17/06/2021 Calling Java from Kotlin | Kotlin

type Java Type Kotlin

java.lang.Object kotlin.Any!

java.lang.Cloneable kotlin.Cloneable!

java.lang.Comparable kotlin.Comparable!

java.lang.Enum kotlin.Enum!

java.lang.Annotation kotlin.Annotation!

java.lang.CharSequence kotlin.CharSequence!

java.lang.String kotlin.String!

java.lang.Number kotlin.Number!

java.lang.Throwable kotlin.Throwable!

Les types primitifs encadrés de Java sont mappés sur des types Kotlin nullables :

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 13/23
17/06/2021 Calling Java from Kotlin | Kotlin

type Java Type Kotlin

java.lang.Byte kotlin.Byte?

java.lang.Short kotlin.Short?

java.lang.Integer kotlin.Int?

java.lang.Long kotlin.Long?

java.lang.Character kotlin.Char?

java.lang.Float kotlin.Float?

java.lang.Double kotlin.Double?

java.lang.Boolean kotlin.Boolean?

Notez qu'un type primitif encadré utilisé comme paramètre de type est mappé à un type de plate-
forme : par exemple, List<java.lang.Integer> devient un List<Int!> dans Kotlin.

Les types de collection peuvent être en lecture seule ou modifiables dans Kotlin, donc les collections
de Java sont mappées comme suit (tous les types Kotlin de cette table résident dans le package
kotlin.collections ):

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 14/23
17/06/2021 Calling Java from Kotlin | Kotlin

type Java Type en lecture Type modifiable Kotlin Type de


seule Kotlin

Iterator<T> Iterator<T> MutableIterator<T> (Mutab

Iterable<T> Iterable<T> MutableIterable<T> (Mutab

Collection<T> Collection<T> MutableCollection<T> (Mutab

Set<T> Set<T> MutableSet<T> (Mutab

List<T> List<T> MutableList<T> (Mutab

ListIterator<T> ListIterator<T> MutableListIterator<T> (Mutab

Map<K, V> Map<K, V> MutableMap<K, V> (Mutab

Map.Entry<K, V> Map.Entry<K, V> MutableMap.MutableEntry<K,V> (Mutab


(Mutab

Les tableaux de Java sont mappés comme indiqué ci - dessous :

type Java Type Kotlin

int[] kotlin.IntArray!

String[] kotlin.Array<(out) String>!

Les membres statiques de ces types Java ne sont pas directement accessibles sur les
objets compagnons des types Kotlin. Pour les appeler, utilisez les noms complets
qualifiés des types Java, par exemple java.lang.Integer.toHexString(foo) .

Génériques Java dans Kotlin


https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 15/23
17/06/2021 Calling Java from Kotlin | Kotlin

Les génériques de Kotlin sont un peu différents de ceux de Java (voir Génériques ). Lors de
l'importation de types Java dans Kotlin, les conversions suivantes sont effectuées :

• Les caractères génériques de Java sont convertis en projections de type :

• Foo<? extends Bar> devient Foo<out Bar!>!

• Foo<? super Bar> devient Foo<in Bar!>!

• Les types bruts de Java sont convertis en projections d'étoiles :

• List devient List<*>! c'est List<out Any?>!

Comme ceux de Java, les génériques de Kotlin ne sont pas conservés au moment de l'exécution : les
objets ne transportent pas d'informations sur les arguments de type réels passés à leurs
constructeurs. Par exemple, ArrayList<Integer>() est indiscernable de
ArrayList<Character>() . Cela rend impossible la réalisation de is contrôles prenant en
compte les génériques. Kotlin n'autorise les is vérifications que pour les types génériques projetés
en étoile :

if (a is List<Int>) // Error: cannot check if it is really a List of I


// but
if (a is List<*>) // OK: no guarantees about the contents of the list

tableaux Java
Les tableaux en Kotlin sont invariants, contrairement à Java. Cela signifie que Kotlin ne vous
permettra pas d'attribuer un Array<String> à un Array<Any> , ce qui empêche un éventuel
échec d'exécution. Passer un tableau d'une sous-classe en tant que tableau de super-classe à une
méthode Kotlin est également interdit, mais pour les méthodes Java, cela est autorisé via les types
de plate -forme form Array<(out) String>! .

Les tableaux sont utilisés avec des types de données primitifs sur la plate-forme Java pour éviter le
coût des opérations de boxing/unboxing. Comme Kotlin masque ces détails d'implémentation, une
solution de contournement est nécessaire pour s'interfacer avec le code Java. Il existe des classes
spécialisées pour chaque type de tableau primitif ( IntArray , DoubleArray , CharArray , etc.)
pour gérer ce cas. Ils ne sont pas liés à la Array classe et sont compilés en tableaux primitifs Java
pour des performances maximales.

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 16/23
17/06/2021 Calling Java from Kotlin | Kotlin

Supposons qu'il existe une méthode Java qui accepte un tableau int d'indices :

public class JavaArrayExample {


public void removeIndices(int[] indices) {
// code here...
}
}

Pour transmettre un tableau de valeurs primitives, vous pouvez effectuer les opérations suivantes
dans Kotlin :

val javaObj = JavaArrayExample()


val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndices(array) // passes int[] to method

Lors de la compilation vers le bytecode JVM, le compilateur optimise l'accès aux tableaux afin qu'il
n'y ait pas de surcharge introduite :

val array = arrayOf(1, 2, 3, 4)


array[1] = array[1] * 2 // no actual calls to get() and set() generate
for (x in array) { // no iterator created
print(x)
}

Même lorsque vous naviguez avec un index, il n'introduit aucune surcharge :

for (i in array.indices) { // no iterator created


array[i] += 2
}

Enfin, in -checks n'a pas non plus de surcharge :

if (i in array.indices) { // same as (i >= 0 && i < array.size)


print(array[i])
}

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 17/23
17/06/2021 Calling Java from Kotlin | Kotlin

varargs Java
Les classes Java utilisent parfois une déclaration de méthode pour les indices avec un nombre
variable d'arguments (varargs) :

public class JavaArrayExample {

public void removeIndicesVarArg(int... indices) {


// code here...
}
}

Dans ce cas, vous devez utiliser l'opérateur spread * pour passer le IntArray :

val javaObj = JavaArrayExample()


val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndicesVarArg(*array)

Les opérateurs
Étant donné que Java n'a aucun moyen de marquer les méthodes pour lesquelles il est logique
d'utiliser la syntaxe de l'opérateur, Kotlin permet d'utiliser toutes les méthodes Java avec le bon
nom et la bonne signature en tant que surcharges d'opérateur et autres conventions ( invoke()
etc.) L'appel de méthodes Java utilisant la syntaxe d'appel infixe est interdit.

Exceptions vérifiées
Dans Kotlin, toutes les exceptions sont décochées , ce qui signifie que le compilateur ne vous oblige
pas à en intercepter aucune. Ainsi, lorsque vous appelez une méthode Java qui déclare une
exception vérifiée, Kotlin ne vous oblige pas à faire quoi que ce soit :

fun render(list: List<*>, to: Appendable) {


for (item in list) {

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 18/23
17/06/2021 Calling Java from Kotlin | Kotlin

to.append(item.toString()) // Java would require us to catch I


}
}

Méthodes objet
Lorsque les types Java sont importés dans Kotlin, toutes les références du type
java.lang.Object sont transformées en Any . Comme il Any n'est pas spécifique à la plate-
forme, il déclare uniquement toString() , hashCode() et en equals() tant que membres, afin
de rendre les autres membres java.lang.Object disponibles, Kotlin utilise des fonctions
d'extension .

attendre()/notifier()
Les méthodes wait() et notify() ne sont pas disponibles sur les références de type Any . Leur
utilisation est généralement déconseillée au profit de java.util.concurrent . Si vous avez
vraiment besoin d'appeler ces méthodes, vous pouvez effectuer un transtypage vers
java.lang.Object :

(foo as java.lang.Object).wait()

getClass()
Pour récupérer la classe Java d'un objet, utilisez la java propriété extension sur une référence de
classe :

val fooClass = foo::class.java

Le code ci-dessus utilise une référence de classe liée . Vous pouvez également utiliser la
javaClass propriété d'extension :

val fooClass = foo.javaClass

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 19/23
17/06/2021 Calling Java from Kotlin | Kotlin

cloner()
Pour remplacer clone() , votre classe doit étendre kotlin.Cloneable :

class Example : Cloneable {


override fun clone(): Any { ... }
}

N'oubliez pas Effective Java, 3rd Edition ↗ , Item 13: Override clone judicieusement .

finaliser()
Pour surcharger finalize() , il suffit de le déclarer, sans utiliser le override mot - clé :

class C {
protected fun finalize() {
// finalization logic
}
}

Selon les règles de Java, finalize() ne doit pas être private .

Héritage des classes Java


Au plus une classe Java (et autant d'interfaces Java que vous le souhaitez) peut être un supertype
pour une classe dans Kotlin.

Accéder aux membres statiques


Les membres statiques des classes Java forment des "objets compagnons" pour ces classes. Vous ne
pouvez pas transmettre un tel "objet compagnon" en tant que valeur, mais vous pouvez accéder
explicitement aux membres, par exemple :

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 20/23
17/06/2021 Calling Java from Kotlin | Kotlin

if (Character.isLetter(a)) { ... }

Pour accéder aux membres statiques d'un type Java mappé à un type Kotlin, utilisez le nom qualifié
complet du type Java : java.lang.Integer.bitCount(foo) .

Réflexion Java
La réflexion Java fonctionne sur les classes Kotlin et vice versa. Comme mentionné ci-dessus, vous
pouvez utiliser instance::class.java , ClassName::class.java ou instance.javaClass
pour entrer dans la réflexion Java via java.lang.Class . Ne pas utiliser ClassName.javaClass
à cette fin car il fait référence à ClassName la classe d'objets compagnon de , qui est la même que
ClassName.Companion::class.java et non ClassName::class.java .

Pour chaque type primitif, il existe deux classes Java différentes et Kotlin fournit des moyens
d'obtenir les deux. Par exemple, Int::class.java renverra l'instance de classe représentant le
type primitif lui-même, correspondant à Integer.TYPE en Java. Pour obtenir la classe du type de
wrapper correspondant, utilisez Int::class.javaObjectType , qui est l'équivalent de Java's
Integer.class .

D'autres cas pris en charge incluent l'acquisition d'une méthode getter/setter Java ou d'un champ
de sauvegarde pour une propriété Kotlin, a KProperty pour un champ Java, une méthode ou un
constructeur Java pour a KFunction et vice versa.

Conversions SAM
Kotlin prend en charge les conversions SAM pour les interfaces Java et Kotlin . Cette prise en charge
de Java signifie que les littéraux de fonction Kotlin peuvent être automatiquement convertis en
implémentations d'interfaces Java avec une seule méthode autre que celle par défaut, tant que les
types de paramètres de la méthode d'interface correspondent aux types de paramètres de la
fonction Kotlin.

Vous pouvez l'utiliser pour créer des instances d'interfaces SAM :

val runnable = Runnable { println("This runs in a runnable") }

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 21/23
17/06/2021 Calling Java from Kotlin | Kotlin

...et dans les appels de méthode :

val executor = ThreadPoolExecutor()


// Java signature: void execute(Runnable command)
executor.execute { println("This runs in a thread pool") }

Si la classe Java a plusieurs méthodes prenant des interfaces fonctionnelles, vous pouvez choisir
celle que vous devez appeler en utilisant une fonction d'adaptateur qui convertit un lambda en un
type SAM spécifique. Ces fonctions d'adaptateur sont également générées par le compilateur
lorsque cela est nécessaire :

executor.execute(Runnable { println("This runs in a thread pool") })

Les conversions SAM ne fonctionnent que pour les interfaces, pas pour les classes
abstraites, même si celles-ci n'ont également qu'une seule méthode abstraite.

Utiliser JNI avec Kotlin


Pour déclarer une fonction implémentée en code natif (C ou C++), vous devez la marquer avec le
external modificateur :

external fun foo(x: Int): Double

Le reste de la procédure fonctionne exactement de la même manière qu'en Java.

Vous pouvez également marquer les getters et setters de propriétés comme external :

var myProperty: String


external get
external set

Dans les coulisses, cela créera deux fonctions getMyProperty et setMyProperty , toutes deux
marquées comme external .

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 22/23
17/06/2021 Calling Java from Kotlin | Kotlin

https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 23/23

Vous aimerez peut-être aussi