Académique Documents
Professionnel Documents
Culture Documents
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.*
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.
foo.`is`(bar)
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 2/23
17/06/2021 Calling Java from Kotlin | Kotlin
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 :
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) :
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.
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 :
• É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
@NotNull
Set<@NotNull String> toSet(@NotNull Collection<@NotNull String> element
Lorsque l' @NotNull annotation est manquante dans un argument de type, vous obtenez un type
de plate-forme à la place :
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 :
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 :
Kotlin prend également en charge les annotations de nullabilité sur les limites des paramètres de
type Java. Ajoutons des limites à Base :
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.
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).
@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?`
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 7/23
17/06/2021 Calling Java from Kotlin | Kotlin
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.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
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 .
// 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é.
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 9/23
17/06/2021 Calling Java from Kotlin | Kotlin
@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) :
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.
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.
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
byte kotlin.Byte
short kotlin.Short
int kotlin.Int
long kotlin.Long
char kotlin.Char
float kotlin.Float
double kotlin.Double
boolean kotlin.Boolean
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 12/23
17/06/2021 Calling Java from Kotlin | 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
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
int[] kotlin.IntArray!
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) .
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 :
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 :
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 :
Pour transmettre un tableau de valeurs primitives, vous pouvez effectuer les opérations suivantes
dans Kotlin :
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 :
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) :
Dans ce cas, vous devez utiliser l'opérateur spread * pour passer le IntArray :
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 :
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 18/23
17/06/2021 Calling Java from Kotlin | Kotlin
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 :
Le code ci-dessus utilise une référence de classe liée . Vous pouvez également utiliser la
javaClass propriété d'extension :
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 :
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
}
}
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.
https://kotlinlang.org/docs/java-interop.html#using-jni-with-kotlin 21/23
17/06/2021 Calling Java from Kotlin | Kotlin
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 :
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.
Vous pouvez également marquer les getters et setters de propriétés comme external :
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