Migration von Java nach Kotlin

Migration von Java nach Kotlin

1. Überblick

In diesem Tutorial werden wir uns ansehen, wie wir von Java aufKotlin migrieren können. Während wir uns viele grundlegende Beispiele ansehen, ist dieser Artikel keine Einführung in Kotlin. Für einen speziellen Artikel können Sie mitthis writeup here beginnen.

Hier sehen wir uns grundlegende Beispiele für die Migration unseres Java-Codes nach Kotlin an, z. B. einfache Druckanweisungen, Definieren von Variablen und Verwalten der Nullfähigkeit.

Dann bewegen wir uns in Richtung innerer Bereiche wie Steueranweisungen wie if-else und switch-Anweisungen.

Schließlich definieren wir Klassen und arbeiten mit Sammlungen.

Weitere Lektüre:

Datenklassen in Kotlin

Ein schnelles und praktisches Beispiel für die Verwendung von Datenklassen in Kotlin.

Read more

Sichtbarkeitsmodifikatoren in Kotlin

Entdecken Sie die Sichtbarkeitsmodifikatoren von Kotlin und sehen Sie, wie sie sich von denen in Java unterscheiden.

Read more

Umfassender Leitfaden zur Nullsicherheit in Kotlin

Eine schnelle, praktische Anleitung zu den Null-Sicherheitsfunktionen, die in der Programmiersprache Kotlin integriert sind.

Read more

2. Grundlegende Migrationen

Beginnen wir mit einfachen Beispielen zum Migrieren einfacher Anweisungen.

2.1. Anweisungen drucken

Lassen Sie uns zunächst sehen, wie das Drucken funktioniert. In Java:

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

In Kotlin:

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

2.2. Variablen definieren

In Java:

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

In Kotlin:

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

Wie wir sehen können, sind Semikolons in Kotlin optional. Kotlin verwendet auch eine erweiterte Typinferenz, und es ist nicht erforderlich, Typen explizit zu definieren.

Wann immer wir eine endgültige Variable erstellen möchten, können wir einfach“val” anstelle von“var”. verwenden

2.3. Casting

In Java müssen wir in folgenden Situationen unnötiges Casting durchführen:

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

In Kotlin können wir durch intelligentes Casting eine redundante Besetzung überspringen:

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

2.4. Bitoperationen

Bitoperationen in Kotlin sind viel intuitiver.

Lassen Sie uns dies mit Java in Aktion sehen:

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

Und in 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

In Java:

final String name = null;

String text;
text = null;

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

Daher gibt es in Java keine Einschränkung, Variablen null zuzuweisen und sie zu verwenden. Bei Verwendung einer Variablen müssen wir normalerweise auch eine Nullprüfung durchführen.

Dies ist bei Kotlin nicht der Fall:

val name: String? = null

var lastName: String?
lastName = null

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

Standardmäßig geht Kotlin davon aus, dass die Werte nichtnull. sein dürfen

Wir können der ReferenzfirstName keinenull zuweisen. Wenn wir dies versuchen, führt dies zu einem Compilerfehler. Wenn wir eine nullfähige Referenz erstellen möchten, müssen wir wie in der ersten Zeile das Fragezeichen (?) An die Typdefinition anhängen.

Mehr dazu finden Sie inthis article.

4. String-Operationen

Stringsfunktionieren genauso wie in Java. Wir können ähnliche Operationen wieappend ausführen und auch einen Teil vonString erhalten.

In 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";

In 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()

Das sah ganz einfach aus:

  • Wir könnenStrings unter Verwendung des Zeichens“$” interpolieren, und die Ausdrücke werden zur Laufzeit ausgewertet. In Java könnten wir mitString.format() etwas Ähnliches erreichen

  • Keine Notwendigkeit, mehrzeilige Strings wie in Java zu brechen. Kotlin unterstützt sie sofort mit. Wir müssen nur daran denken, dreifache Anführungszeichen zu verwenden

In Kotlin gibt es kein Symbol für die Fortsetzung der Linie. Da die Grammatik Leerzeichen zwischen fast allen Symbolen zulässt, können wir einfach die folgende Aussage brechen:

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

Wenn die erste Zeile der Anweisung jedoch eine gültige Anweisung ist, funktioniert sie nicht:

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

Um solche Probleme zu vermeiden, wenn lange Anweisungen in mehrere Zeilen aufgeteilt werden, können Klammern verwendet werden:

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

5. Schleifen und Steueranweisungen

Wie in jeder anderen Programmiersprache gibt es auch in Kotlin Steueranweisungen und Schleifen für sich wiederholende Aufgaben.

5.1. Für Schleife

In Java gibt es verschiedene Arten von Schleifen zum Durchlaufen einer Sammlung oderMap,wie:

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()) { }

In Kotlin haben wir etwas Ähnliches, aber einfacheres. Wie wir bereits wissen, versucht Kotlins Syntax, die natürliche Sprache so gut wie möglich nachzuahmen:

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 undWhen

Wir könnenswitch Anweisungen in Java verwenden, um selektive Entscheidungen zu treffen:

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";
}

In Kotlin verwenden wir anstelle der Anweisungswitchdie Anweisungwhen, um selektive Entscheidungen zu treffen:

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" }
}

Die Anweisungwhenkann als Ausdruck oder Anweisung mit oder ohne Argument fungieren:

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

6. Klassen

In Java definieren wir eine Modellklasse und begleiten sie mit Standardsetzern und Gettern:

package com.example;

public class Person {

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

    // setters and getters
}

In Kotlin werden Getter und Setter automatisch generiert:

package com.example

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

Die Änderung der Sichtbarkeit von Getter / Setter kann ebenfalls geändert werden. Beachten Sie jedoch, dass die Sichtbarkeit des Getters mit der Sichtbarkeit der Eigenschaft übereinstimmen muss.

In Kotlin verfügt jede Klasse über die folgenden Methoden (die überschrieben werden können):

  • toString (lesbare Zeichenfolgendarstellung für ein Objekt)

  • hashCode (liefert eine eindeutige Kennung für ein Objekt)

  • equals (wird verwendet, um zwei Objekte derselben Klasse zu vergleichen, um festzustellen, ob sie identisch sind)

7. Sammlungen

Nun, wir wissen, dass Sammlungen ein leistungsfähiges Konzept für jede Programmiersprache sind. Einfach ausgedrückt, wir können ähnliche Objekte sammeln und Operationen mit ihnen ausführen. Werfen wir einen Blick auf 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");

Jetzt können wir in Kotlin ähnliche Sammlungen haben:

val numbers = listOf(1, 2, 3)

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

Das Ausführen von Operationen ist ebenfalls interessant, wie in Java:

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

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

Als nächstes können wir die gleichen Operationen in Kotlin auf viel einfachere Weise ausführen:

numbers.forEach {
    println(it)
}

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

Lassen Sie uns ein letztes Beispiel zum Sammeln von geraden und ungeraden Zahlen inMap vonString als Schlüssel undList vonIntegers als Wert untersuchen. In Java müssen wir schreiben:

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);
}

In Kotlin:

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

8. Fazit

Dieser Artikel dient als erste Hilfe bei der Umstellung von Java auf Kotlin.

Während der Vergleich nur ein Hinweis darauf war, wie einfach und intuitiv Kotlin sein kann, sind andere Artikelcan be found here.