JavaからKotlinへの移行

JavaからKotlinへの移行

1. 概要

このチュートリアルでは、JavaからKotlinに移行する方法を見ていきます。 多くの基本的な例を見ていきますが、この記事はKotlinの紹介ではありません。 専用の記事の場合は、this writeup hereから始めることができます。

ここでは、単純なprintステートメント、変数の定義、null可能性の管理など、JavaコードをKotlinに移行する基本的な例を見ていきます。

次に、if-elseやswitchステートメントなどの制御ステートメントなどの内部領域に移動します。

最後に、クラスの定義とコレクションの操作に移ります。

参考文献:

Kotlinのデータクラス

Kotlinでデータクラスを使用する迅速で実用的な例。

Kotlinの可視性修飾子

Kotlinの可視性修飾子を見つけて、Javaで見られるものとどのように異なるかを確認してください。

KotlinのNull安全性に関する包括的なガイド

Kotlinプログラミング言語に組み込まれたヌル安全機能の迅速で実用的なガイド。

2. 基本的な移行

簡単なステートメントを移行する方法の簡単な例から始めましょう。

2.1. ステートメントを印刷する

まず、印刷がどのように機能するかを見てみましょう。 Javaの場合:

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

コトリンでは:

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

2.2. 変数の定義

Javaの場合:

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

コトリンでは:

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

ご覧のとおり、Kotlinのセミコロンはオプションです。 Kotlinは拡張型推論も利用しているため、型を明示的に定義する必要はありません。

最終変数を作成するときはいつでも、“var”.の代わりに“val”を使用できます。

2.3. 鋳造

Javaでは、次のような状況で不必要なキャストを実行する必要があります。

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

Kotlinでは、スマートキャストにより、冗長なキャストをスキップできます。

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

2.4. ビット演算

Kotlinのビット操作ははるかに直感的です。

これをJavaで実際に見てみましょう。

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

そして、コトリンでは:

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. ヌル-安全性

Javaの場合:

final String name = null;

String text;
text = null;

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

したがって、Javaには、変数にnullを割り当てて使用するという制限はありません。 変数を使用している間、通常はnullチェックも行う必要があります。

これはKotlinには当てはまりません。

val name: String? = null

var lastName: String?
lastName = null

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

デフォルトでは、Kotlinは値をnull.にすることはできないと想定しています

nullを参照firstNameに割り当てることはできません。割り当てようとすると、コンパイラエラーが発生します。 NULL可能参照を作成する場合は、最初の行で行ったように、型定義に疑問符(?)を追加する必要があります。

これについての詳細はthis articleにあります。

4. 文字列操作

Stringsは、Javaの場合と同じように機能します。 appendのような同様の操作を実行し、Stringの一部を取得することもできます。

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

コトリンでは:

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

それは非常に簡単に見えました:

  • “$”文字を使用してStringsを補間でき、式は実行時に評価されます。 Javaでは、String.format()を使用して同様のことを実現できます。

  • Javaのように複数行の文字列を分割する必要はありません。 Kotlinは、すぐに使用できるようにサポートしています。 三重引用符を使用することを忘れないでください

Kotlinには行継続のシンボルはありません。 その文法により、ほぼすべてのシンボル間にスペースを入れることができるため、ステートメントを中断することができます。

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

ただし、ステートメントの最初の行が有効なステートメントである場合、それは機能しません。

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

長いステートメントを複数行に分割する際にこのような問題を回避するには、括弧を使用できます。

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

5. ループと制御ステートメント

他のプログラミング言語と同じように、Kotlinにも、反復タスク用の制御ステートメントとループがあります。

5.1. ループ用

Javaには、コレクションを反復処理するためのさまざまな種類のループ、または次のようなMap,があります。

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には、似たようなものがありますが、よりシンプルです。 すでによく知っているように、Kotlinの構文は、可能な限り自然言語を模倣しようとしています。

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およびWhen

Javaでswitchステートメントを使用して、選択的な決定を行うことができます。

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

Kotlinでは、switchステートメントの代わりに、whenステートメントを使用して選択的な決定を行います。

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

whenステートメントは、引数の有無にかかわらず、式またはステートメントとして機能できます。

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

6. クラス

Javaでは、モデルクラスを定義し、それらに標準のセッターとゲッターを添付します。

package com.example;

public class Person {

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

    // setters and getters
}

Kotlinでは、ゲッターとセッターは自動生成されます。

package com.example

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

ゲッター/セッターの可視性の変更も変更できますが、ゲッターの可視性はプロパティの可視性と同じである必要があることに注意してください。

Kotlinでは、すべてのクラスに次のメソッドがあります(オーバーライド可能):

  • toString(オブジェクトの読み取り可能な文字列表現)

  • hashCode(オブジェクトの一意の識別子を提供します)

  • equals(同じクラスの2つのオブジェクトを比較して、それらが同じかどうかを確認するために使用されます)

7. コレクション

コレクションは、あらゆるプログラミング言語の強力な概念であることがわかっています。簡単に言えば、同様の種類のオブジェクトを収集し、それらのオブジェクトに対して操作を実行できます。 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");

現在、Kotlinでは、同様のコレクションを使用できます。

val numbers = listOf(1, 2, 3)

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

Javaのように、操作の実行も興味深いものです。

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

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

次に、Kotlinで同じ操作をより簡単な方法で実行できます。

numbers.forEach {
    println(it)
}

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

StringMapをキーとして、ListIntegersを値として、偶数と奇数を収集する最後の例を見てみましょう。 Javaでは、次のように書く必要があります。

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

コトリンでは:

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

8. 結論

この記事は、JavaからKotlinに移行する際の最初のヘルプとして役立ちます。

比較は、Kotlinがいかにシンプルで直感的であるかを示すヒントにすぎませんでしたが、他の記事はcan be found hereです。