Migration de Java vers Kotlin

Migration de Java vers Kotlin

1. Vue d'ensemble

Dans ce didacticiel, nous allons examiner comment nous pouvons migrer de Java versKotlin. Bien que nous examinions de nombreux exemples de base, cet article n'est pas une introduction à Kotlin. Pour un article dédié, vous pouvez commencer parthis writeup here.

Ici, nous allons examiner des exemples de base de migration de notre code Java vers Kotlin, comme de simples instructions d'impression, la définition de variables, la gestion de la nullité.

Ensuite, nous nous dirigerons vers des domaines internes tels que les instructions de contrôle comme if-else et les instructions switch.

Enfin, nous passons à la définition de classes et à l'utilisation de collections.

Lectures complémentaires:

Classes de données en Kotlin

Un exemple rapide et pratique d’utilisation des classes de données dans Kotlin.

Read more

Modificateurs de visibilité à Kotlin

Découvrez les modificateurs de visibilité de Kotlin et voyez en quoi ils diffèrent de ceux trouvés dans Java.

Read more

Guide complet sur la sécurité nulle à Kotlin

Un guide rapide et pratique sur les fonctions de sécurité null intégrées au langage de programmation Kotlin.

Read more

2. Migrations de base

Commençons par des exemples simples sur la façon de migrer des instructions simples.

2.1. Imprimer les déclarations

Pour commencer, voyons comment fonctionne l'impression. En Java:

System.out.print("Hello, example!");
System.out.println("Hello, example!");

À Kotlin:

print("Hello, example!")
println("Hello, example!")

2.2. Définition de variables

En Java:

final int a;
final int b = 21;
int c;
int d = 25;
d = 23;
c = 21;

À Kotlin:

val a: Int
val b = 21
var c: Int
var d = 25
d = 23
c = 21

Comme nous pouvons le constater, les points-virgules de Kotlin sont facultatifs. Kotlin utilise également l'inférence de type améliorée, et nous n'avons pas besoin de définir explicitement les types.

Chaque fois que nous voulons créer une variable finale, nous pouvons simplement utiliser“val” au lieu de“var”.

2.3. Moulage

En Java, nous devons effectuer des conversions inutiles dans des situations telles que:

if(str instanceof String){
    String result = ((String) str).substring(1);
}

Dans Kotlin, le casting intelligent nous permet de sauter un casting redondant:

if (str is String) {
    val result = str.substring(1)
}

2.4. Opérations sur les bits

Les opérations de bits dans Kotlin sont beaucoup plus intuitives.

Voyons cela en action, avec Java:

int orResult   = a | b;
int andResult  = a & b;
int xorResult  = a ^ b;
int rightShift = a >> 2;
int leftShift  = a << 2;

Et à Kotlin:

var orResult   = a or b
var andResult  = a and b
var xorResult  = a xor b
var rightShift = a shr 2
var leftShift  = a shl 2

3. Null-Safety

En Java:

final String name = null;

String text;
text = null;

if(text != null){
    int length = text.length();
}

Il n'y a donc aucune restriction en Java pour attribuer null aux variables et les utiliser. Lorsque vous utilisez une variable, nous sommes généralement obligés de faire une vérification nulle.

Ce n'est pas le cas avec Kotlin:

val name: String? = null

var lastName: String?
lastName = null

var firstName: String
firstName = null // Compilation error!!

Par défaut, Kotlin suppose que les valeurs ne peuvent pas êtrenull.

Nous ne pouvons pas affecternull à la référencefirstName, et si nous essayons de le faire, cela provoquera une erreur du compilateur. Si nous voulons créer une référence nullable, nous devons ajouter le point d'interrogation (?) À la définition de type, comme nous l'avons fait à la première ligne.

Pour en savoir plus, consultezthis article.

4. Opérations sur les chaînes

Strings fonctionne de la même manière qu'en Java. Nous pouvons faire des opérations similaires commeappend et obtenir une partie d'unString également.

En Java:

String name = "John";
String lastName = "Smith";
String text = "My name is: " + name + " " + lastName;
String otherText = "My name is: " + name.substring(2);

String text = "First Line\n" +
  "Second Line\n" +
  "Third Line";

À Kotlin:

val name = "John"
val lastName = "Smith"
val text = "My name is: $name $lastName"
val otherText = "My name is: ${name.substring(2)}"

val text = """
  First Line
  Second Line
  Third Line
""".trimMargin()

Cela semblait assez facile:

  • Nous pouvons interpolerStrings en utilisant le caractère“$”, et les expressions seront évaluées à l'exécution. En Java, nous pourrions réaliser quelque chose de similaire en utilisantString.format()

  • Pas besoin de casser des chaînes multilignes comme en Java. Kotlin les prend en charge immédiatement. Nous devons juste nous rappeler d’utiliser des guillemets triples

Il n'y a pas de symbole pour la continuation de ligne dans Kotlin. Comme sa grammaire permet de laisser des espaces entre presque tous les symboles, on peut simplement casser la phrase:

val text = "This " + "is " + "a " +
  "long " + "long " + "line"

Cependant, si la première ligne de l'instruction est une instruction valide, cela ne fonctionnera pas:

val text = "This " + "is " + "a "
  + "long " + "long " + "line" // syntax error

Pour éviter de tels problèmes lors de la rupture d'instructions longues sur plusieurs lignes, nous pouvons utiliser des parenthèses:

val text = ("This " + "is " + "a "
  + "long " + "long " + "line") // no syntax error

5. Boucles et instructions de contrôle

Comme tout autre langage de programmation, dans Kotlin également, nous avons des instructions de contrôle et des boucles pour les tâches répétitives.

5.1. Pour boucle

En Java, nous avons différents types de boucles pour itérer sur une collection, ou unMap,comme:

for (int i = 1; i < 11 ; i++) { }

for (int i = 1; i < 11 ; i+=2) { }

for (String item : collection) { }

for (Map.Entry entry: map.entrySet()) { }

À Kotlin, nous avons quelque chose de similaire, mais plus simple. Comme nous le savons déjà, la syntaxe de Kotlin essaie d'imiter le plus possible le langage naturel:

for (i in 1 until 11) { }

for (i in 1..10 step 2) { }

for (item in collection) { }
for ((index, item) in collection.withIndex()) { }

for ((key, value) in map) { }

5.2. Switch etWhen

Nous pouvons utiliser les instructionsswitch en Java pour prendre des décisions sélectives:

final int x = ...; // some value
final String xResult;

switch (x) {
    case 0:
    case 11:
        xResult = "0 or 11";
        break;
    case 1:
    case 2:
    //...
    case 10:
        xResult = "from 1 to 10";
        break;
    default:
        if(x < 12 && x > 14) {
        xResult = "not from 12 to 14";
        break;
    }

    if(isOdd(x)) {
        xResult = "is odd";
        break;
    }

    xResult = "otherwise";
}

final int y = ...; // some value;
final String yResult;

if(isNegative(y)){
    yResult = "is Negative";
} else if(isZero(y)){
    yResult = "is Zero";
} else if(isOdd(y)){
    yResult = "is Odd";
} else {
    yResult = "otherwise";
}

Dans Kotlin, au lieu d'une instructionswitch, nous utilisons une instructionwhen pour prendre des décisions sélectives:

val x = ... // some value
val xResult = when (x) {
  0, 11 -> "0 or 11"
  in 1..10 -> "from 1 to 10"
  !in 12..14 -> "not from 12 to 14"
  else -> if (isOdd(x)) { "is odd" } else { "otherwise" }
}

L'instructionwhen peut agir comme une expression ou une instruction, avec ou sans argument:

val y = ... // some value
val yResult = when {
  isNegative(y) -> "is Negative"
  isZero(y) -> "is Zero"
  isOdd(y) -> "is odd"
  else -> "otherwise"
}

6. Des classes

En Java, nous définissons une classe de modèle et les accompagnons avec des setters et des getters standard:

package com.example;

public class Person {

    private long id;
    private String name;
    private String brand;
    private long price;

    // setters and getters
}

À Kotlin, les getters et les setters sont générés automatiquement:

package com.example

class Person {
  var id: Long = 0
  var name: String? = null
  var brand: String? = null
  var price: Long = 0
}

La modification de la visibilité getter / setter peut également être modifiée, mais gardez à l'esprit que la visibilité du getter doit être la même que celle de la propriété.

Dans Kotlin, chaque classe est fournie avec les méthodes suivantes (pouvant être remplacées):

  • toString (représentation sous forme de chaîne lisible pour un objet)

  • hashCode (fournit un identifiant unique pour un objet)

  • equals (utilisé pour comparer deux objets de la même classe pour voir s'ils sont identiques)

7. Des collections

Nous savons que les collections sont un concept puissant, quel que soit le langage de programmation utilisé. En termes simples, nous pouvons collecter des types d'objets similaires et effectuer des opérations avec / sur eux. Jetons un coup d'œil à ceux de Java:

final List numbers = Arrays.asList(1, 2, 3);

final Map map = new HashMap();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");

// Java 9
final List numbers = List.of(1, 2, 3);

final Map map = Map.of(
  1, "One",
  2, "Two",
  3, "Three");

Maintenant, à Kotlin, nous pouvons avoir des collections similaires:

val numbers = listOf(1, 2, 3)

val map = mapOf(
  1 to "One",
  2 to "Two",
  3 to "Three")

Effectuer des opérations est également intéressant, comme en Java:

for (int number : numbers) {
    System.out.println(number);
}

for (int number : numbers) {
    if(number > 5) {
        System.out.println(number);
    }
}

Ensuite, nous pouvons effectuer les mêmes opérations dans Kotlin d’une manière beaucoup plus simple:

numbers.forEach {
    println(it)
}

numbers
  .filter  { it > 5 }
  .forEach { println(it) }

Étudions un dernier exemple sur la collecte de nombres pairs et impairs dans unMap deString en tant que clés, etList deIntegers en tant que valeur. En Java, nous devrons écrire:

final Map> groups = new HashMap<>();
for (int number : numbers) {
    if((number & 1) == 0) {
        if(!groups.containsKey("even")) {
            groups.put("even", new ArrayList<>());
        }

        groups.get("even").add(number);
        continue;
    }

    if(!groups.containsKey("odd")){
        groups.put("odd", new ArrayList<>());
    }

    groups.get("odd").add(number);
}

À Kotlin:

val groups = numbers.groupBy {
  if (it and 1 == 0) "even" else "odd"
}

8. Conclusion

Cet article sert d’aide initiale pour passer de Java à Kotlin.

Alors que la comparaison n'était qu'un indice de la simplicité et de l'intuitivité de Kotlin, d'autres articlescan be found here.