1. 序章

このチュートリアルでは、Kotlin言語のconst、var、およびvalキーワードの主な違いを概要で説明します。

これらのキーワードをコンテキストに入れるために、それらを同等のJavaと比較します。

2. タイピングを理解する

これらのキーワードを理解するには、言語が従うことができる型システムの2つの主要なカテゴリである外延型と推論型を理解する必要があります。

2.1. マニフェストタイピング

すべての言語は、プログラム内でデータを格納および操作するためのさまざまなプリミティブデータ型を提供します。 マニフェスト型付けの規律に従ったプログラミング言語では、プログラム内でデータ型を明示的に定義する必要があります。

バージョン10までのJavaは、この規律に厳密に従っています。 たとえば、プログラム内に数値を格納する場合は、intなどのデータ型を定義する必要があります。

int myVariable = 3;

2.2. 推測される入力

Javaとは異なり、Kotlinは推論された型付け規律に従います。 型推論をサポートする言語は、コンパイル時にプログラム内のデータ型を自動的に検出します。

この検出は、開発者として、使用しているデータ型について心配する必要がないことを意味します。

3. var

まず、 var、可変の非最終変数を表すKotlinのキーワード。 初期化されると、変数が保持するデータを自由に変更できます。

これがどのように機能するかを見てみましょう。

var myVariable = 1

舞台裏では、myVariableIntデータ型で初期化されます。

Kotlinは型推論を使用しますが、には、変数を初期化するときにデータ型を指定するオプションもあります。

var myVariable: Int = 1

1つのデータ型として宣言された後、間違った型の値で初期化された変数は、エラーになります。

var myVariable: Int = b //ERROR!

4. val

Kotlinのvalキーワードは、varキーワードと同じでほとんど機能しますが、重要な違いが1つあります。変数は読み取り専用です。 valの使用は[ X166X]最後のキーワードを使用してJavaで新しい変数を宣言するのとよく似ています。

たとえば、Kotlinでは次のように記述します。

val name: String = "Baeldung"

一方、Javaでは、次のように記述します。

final String name = "Baeldung";

Javaのfinal変数と同様に、Kotlinの val 変数には、宣言されたとおりに値を割り当てるか、Classコンストラクターで値を割り当てる必要があります。

class Address(val street: String) {
    val name: String = "Baeldung"
}

5. const

valと同様に、constキーワードで定義された変数は不変です。 ここでの違いは、 const が、コンパイル時に既知の変数に使用されることです。

変数constの宣言は、Javaでstaticキーワードを使用するのとよく似ています。

Kotlinでconst変数を宣言する方法を見てみましょう。

const val WEBSITE_NAME = "Baeldung"

また、Javaで記述された類似のコードは次のようになります。

final static String WEBSITE_NAME = "Baeldung";

5.1. 一定のインライン化

Kotlin 1.1以降、Kotlinコンパイラはconstval値を使用されている場所にインライン化します。 たとえば、簡単な例を考えてみましょう。

const val VALUE: String = "constant"

fun main() {
    println("$VALUE is inlined")
}

一見すると、Kotlinコンパイラはクラスから静的フィールド値を取得し、それを” inlined”textと連結していると思うかもしれません。 ただし、 const val はインライン化されているため、 VALUE 定数が使用されている場合は常に、コンパイラは「定数」リテラルをコピーします。 この定数のインライン化は、クラスから静的な値を取得するよりもはるかに効率的です。

インライン化が実際に内部で行われていることを確認するために、バイトコードを確認できます。 まず、kotlincを使用してKotlinファイルをコンパイルする必要があります。

$ kotlinc Main.kt

次に、 javap を使用して、生成されたバイトコードを確認できます。

$ javap -c -p -v MainKt
// truncated
0: ldc           #16                 // String constant is inlined
2: astore_0
3: iconst_0
4: istore_1
5: getstatic     #22                 // Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_0
9: invokevirtual #28                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
12: return

上に示したように、インデックス0では、「定数」リテラルが連結のためにコピーされます。 したがって、クラスの静的フィールドから値をフェッチするためのgetstaticはありません。

つまり、 const valsは静的フィールドのように見えても、public static finalfieldsとして実装されていません。 簡単に言えば、 constvalは単なるコンパイラの幻想です。

6. 結論

この記事では、マニフェスト型と推定型の違いについて簡単に説明しました。

次に、Kotlinの var、 val 、およびconstキーワードの違いを調べました。