1概要

このチュートリアルでは、JVMの世界で新しい言語となっているKotlinと、クラス、継承、条件付きステートメント、ループ構造などの基本機能について説明します。

それから、Kotlinを魅力的な言語にする主な機能のいくつかを見ていきます。それには、null安全性、データクラス、拡張関数、そして

String

テンプレートが含まれます。


2 Mavenの依存関係

MavenプロジェクトでKotlinを使用するには、Kotlin標準ライブラリを

pom.xml

に追加する必要があります。

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>1.0.4</version>
</dependency>

KotlinのJUnitサポートを追加するには、以下の依存関係も含める必要があります。

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-test-junit</artifactId>
    <version>1.0.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>


https://search.maven.org/classic/#search%7C1%7Cg%3A%22org.jetbrains.kotlin%22%20AND%20a%3A%22kotlin-stdlib%22

の最新バージョンを見つけることができます。

kotlin-stdlib

[Maven Centralの[kotlin-test-junit]、およびhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22junit%22%20AND%20a%3A%22junit%22[junit]。

最後に、Mavenビルドを実行するためにソースディレクトリとKotlinプラグインを設定する必要があります。

<build>
    <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
    <plugins>
        <plugin>
            <artifactId>kotlin-maven-plugin</artifactId>
            <groupId>org.jetbrains.kotlin</groupId>
            <version>1.0.4</version>
            <executions>
                <execution>
                    <id>compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

あなたはhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.jetbrains.kotlin%22%20AND%20a%3A%22kotlin-maven-plugin%の最新バージョンを見つけることができます。 Maven Centralの22[kotlin-maven-plugin]。

3.基本的な構文

Kotlin言語の基本的な構成要素を見てみましょう。

Javaと多少の類似点があります(例:パッケージの定義も同じです)違いを見てみましょう。

3.1. 関数を定義する


Int

戻り型の2つのIntパラメータを持つ関数を定義しましょう。

fun sum(a: Int, b: Int): Int {
    return a + b
}

3.2. ローカル変数の定義

代入1回(読み取り専用)ローカル変数

val a: Int = 1
val b = 1
val c: Int
c = 1

変数

b

の型はKotlinコンパイラによって推論されることに注意してください。可変変数を定義することもできます。

var x = 5
x += 1

4.オプションのフィールド

Kotlinには、null入力可能なフィールドを定義するための基本的な構文があります(オプション)。フィールドの型がNULL可能であることを宣言したい場合は、疑問符を付けた型を使用する必要があります。

val email: String?

NULL可能フィールドを定義したとき、それに

null

を代入することは完全に有効です。

val email: String? = null

つまり、Eメールフィールドには__nullが含まれる可能性があります。

val email: String = "value"

それから私達は私達が電子メールを宣言するのと同じステートメントで電子メールフィールドに値を割り当てる必要があります。 null値を持つことはできません。 Kotlinの安全性については後のセクションで取り上げます。


5クラス

商品の特定のカテゴリを管理するための単純なクラスを作成する方法を説明しましょう。以下の

ItemManager

クラスには、

categoryId



dbConnection

の2つのフィールドとオプションの

email

フィールドを設定するデフォルトのコンストラクタがあります。

class ItemManager(val categoryId: String, val dbConnection: String) {
    var email = ""
   //...
}

その

ItemManager(…​)

コンストラクトは、コンストラクターとクラス内に2つのフィールド(

categoryId

および

dbConnection

)を作成します。

私たちのコンストラクタはその引数に

val

キーワードを使うことに注意してください – これは対応するフィールドが

final

で不変であることを意味します。


var

キーワードを使用した場合(

email

フィールドを定義したときのように)、それらのフィールドは可変になります。

デフォルトのコンストラクタを使用してItemManagerのインスタンスを作成しましょう。

ItemManager("cat__id", "db://connection")

名前付きパラメータを使用して

ItemManager

を構築できます。この例のように同じ型の2つのパラメータを取る関数が好きなときにとても便利です。あなたはそれらの順序を混同したくありません。命名パラメータを使用して、どのパラメータが割り当てられるかを明示的に書くことができます。

ItemManager

クラスには

categoryId



dbConnection

の2つのフィールドがあるため、両方とも名前付きパラメータを使用して参照できます。

ItemManager(categoryId = "catId", dbConnection = "db://Connection")

関数にもっと多くの引数を渡す必要があるときにとても便利です。

追加のコンストラクタが必要な場合は、

constructor

キーワードを使用してそれらを定義します。

email

フィールドも設定する別のコンストラクタを定義しましょう。

constructor(categoryId: String, dbConnection: String, email: String)
  : this(categoryId, dbConnection) {
    this.email = email
}

このコンストラクタは、emailフィールドを設定する前に、上で定義したデフォルトのコンストラクタを呼び出します。また、デフォルトコンストラクタの

val

キーワードを使用して

categoryId



dbConnection

を不変にするようにすでに定義しているので、追加のコンストラクタで

val

キーワードを繰り返す必要はありません。

それでは、追加のコンストラクタを使用してインスタンスを作成しましょう。

ItemManager("cat__id", "db://connection", "[email protected]")


ItemManager

でインスタンスメソッドを定義したい場合は、

fun

キーワードを使用して定義します。

fun isFromSpecificCategory(catId: String): Boolean {
    return categoryId == catId
}


6. 継承

デフォルトでは、Kotlinのクラスは拡張のために閉じられています – これはJavaで

final

とマークされたクラスと同等です。

クラスが拡張用に開かれていることを指定するには、クラスを定義するときに

open

キーワードを使用します。

拡張可能な

Item

クラスを定義しましょう。

open class Item(val id: String, val name: String = "unknown__name") {
    open fun getIdOfItem(): String {
        return id
    }
}


getIdOfItem()

メソッドもopenと表記しています。これにより、上書きすることができます。

それでは、

Item

クラスを拡張し、

getIdOfItem()

メソッドをオーバーライドしましょう。

class ItemWithCategory(id: String, name: String, val categoryId: String) : Item(id, name) {
    override fun getIdOfItem(): String {
        return id + name
    }
}


7. 条件付きステートメント

Kotlinでは、条件付きステートメント

if

は何らかの値を返す関数と同等です。例を見てみましょう。

fun makeAnalyisOfCategory(catId: String): Unit {
    val result = if (catId == "100") "Yes" else "No"
    println(result)
}

この例では、

catId

が“ 100”に等しい場合、条件ブロックは“ Yes”を返し、そうでなければ“ No”を返します。

通常の

if



else

ブロックを作成できます。

val number = 2
if (number < 10) {
    println("number less that 10")
} else if (number > 10) {
    println("number is greater that 10")
}

Kotlinには非常に便利な

when

コマンドがあり、これは高度なswitch文のように動作します。

val name = "John"
when (name) {
    "John" -> println("Hi man")
    "Alice" -> println("Hi lady")
}

8.コレクション

Kotlinには2種類のコレクションがあります。それは可変と不変です。

不変コレクションを作成すると、それは読み取り専用です。

val items = listOf(1, 2, 3, 4)

そのリストにはadd function要素はありません。

変更可能な可変リストを作成したい場合は、

mutableListOf()

メソッドを使用する必要があります。

val rwList = mutableListOf(1, 2, 3)
rwList.add(5)

可変リストには

add()

メソッドがあるので、それに要素を追加することができます。

他の種類のコレクションと同等の方法もあります。


mutableMapOf()、mapOf()、setOf()、mutableSetOf()

9.例外

例外処理のメカニズムは、Javaのメカニズムと非常によく似ています。

すべての例外クラスは__Throwableを継承しています。例外にはメッセージ、スタックトレース、およびオプションの原因が必要です。

Kotlinのすべての例外はチェックされていません

、これはコンパイラがそれらをキャッチすることを強制していないことを意味します。

例外オブジェクトをスローするには、throw式を使用する必要があります。

throw Exception("msg")

例外の処理は

try …​ catchブロックを使用して行われます(finally

オプション)。

try {

}
catch (e: SomeException) {

}
finally {

}

10.ラムダ

Kotlinでは、ラムダ関数を定義し、それらを他の関数への引数として渡すことができます。

単純なラムダを定義する方法を見てみましょう。

val sumLambda = { a: Int, b: Int -> a + b }

引数として

Int

型の2つの引数を取り、

Int.

を返す

sumLambda

関数を定義しました。

ラムダを渡すことができます:

@Test
fun givenListOfNumber__whenDoingOperationsUsingLambda__shouldReturnProperResult() {
   //given
    val listOfNumbers = listOf(1, 2, 3)

   //when
    val sum = listOfNumbers.reduce { a, b -> a + b }

   //then
    assertEquals(6, sum)
}

** 11ループ構成

Kotlinでは、コレクションのループは標準の

for..in

構文を使って行うことができます。

val numbers = arrayOf("first", "second", "third", "fourth")

for (n in numbers) {
    println(n)
}

整数の範囲にわたって反復したい場合は、範囲構成を使用できます。

for (i in 2..9 step 2) {
    println(i)
}

上記の例の範囲は両側を含むことに注意してください。

step

パラメータはオプションであり、各反復でカウンタを2回インクリメントするのと同じです。出力は以下のようになります。

2
4
6
8

次のように

Int

クラスで定義されている

rangeTo()

関数を使用できます。

1.rangeTo(10).map{ it **  2 }

結果には以下が含まれます(

rangeTo()

も包括的です)。

----[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]----


12. ヌル安全性

Kotlinの重要な機能の1つである、安全性の無効化を言語に組み込みます。なぜこれが便利なのかを説明するために、

Item

オブジェクトを返す単純なサービスを作成します。

class ItemService {
    fun findItemNameForId(id: String): Item? {
        val itemId = UUID.randomUUID().toString()
        return Item(itemId, "name-$itemId");
    }
}

注意すべき重要なことは、そのメソッドの戻り型です。疑問符が続くオブジェクトです。これはKotlin言語からの構成体です。つまり、そのメソッドから返される

Item

はnullになる可能性があります。

私たちはコンパイル時にそのケースを処理する必要があり、そのオブジェクトに対して何をしたいのかを決定します(それはJava 8の

Optional <T>

型とほぼ同等です)。

メソッドシグネチャに疑問符のないタイプがある場合:

fun findItemNameForId(id: String): Item

それがコンパイラとKotlin言語によって保証されているので、コードを呼び出すことはnullケースを扱う必要はないでしょう、その返されたオブジェクトはnullであることができません。

それ以外の場合、** メソッドに渡されるnull許容オブジェクトがあり、その場合が処理されないと、コンパイルされません。

Kotlin型安全のテストケースを書きましょう。

val id = "item__id"
val itemService = ItemService()

val result = itemService.findItemNameForId(id)

assertNotNull(result?.let { it -> it.id })
assertNotNull(result!!.id)

ここでは、メソッド

findItemNameForId()を実行した後の

返される型はKotlin

Nullable

です。そのオブジェクトのフィールド(

id

)にアクセスするには、コンパイル時にそのケースを処理する必要があります。メソッド

let()

は、結果がNULL不可の場合にのみ実行されます。

Id

フィールドはnullセーフなので、ラムダ関数内でアクセスできます。

null入力可能オブジェクトフィールドにアクセスするもう1つの方法は、Kotlin演算子__ !!を使用することです。

if (result == null){
    throwNpe();
}
return result;

Kotlinはそのオブジェクトが

null

であるかどうかを調べます。もしそうであれば__NullPointerExceptionを投げます。

関数

throwNpe()

はKotlinの内部関数です。


13. データクラス

Kotlinで見つけることができるとても良い言語構成はデータクラスです(それはScala言語からの「case class」と同等です)。そのようなクラスの目的はデータを保持することだけです。この例では、データのみを保持する

Item

クラスがあります。

data class Item(val id: String, val name: String)

コンパイラは、メソッド

hashCode()



equals()

、および

toString()

を作成します。

val

キーワードを使用して、データクラスを不変にすることをお勧めします。データクラスはデフォルトのフィールド値を持つことができます:

data class Item(val id: String, val name: String = "unknown__name")


name

フィールドにはデフォルト値 “unknown

name”

.__があることがわかります。


14. 拡張機能

サードパーティライブラリの一部であるクラスがあるとしますが、追加のメソッドでそれを拡張したいと思います。 Kotlinでは、これを拡張関数を使って行うことができます。

要素のリストがあり、そのリストからランダムな要素を取り出したいという例を考えてみましょう。サードパーティの

List

クラスに新しい関数

random()

を追加します。

これがKotlinの様子です。

fun <T> List<T>.random(): T? {
    if (this.isEmpty()) return null
    return get(ThreadLocalRandom.current().nextInt(count()))
}

ここで注意すべき最も重要なことはメソッドのシグネチャです。

このメソッドには、この追加のメソッドを追加するクラスの名前がプレフィックスとして付けられます。

拡張メソッドの内部では、リストのスコープを操作します。したがって、

this

を使用すると、

isEmpty()

や__count()のようなリストインスタンスメソッドへのアクセスが許可されます。その範囲内です:

fun <T> getRandomElementOfList(list: List<T>): T? {
    return list.random()
}

リストを受け取り、それから以前に定義されたカスタム拡張関数

random()

を実行するメソッドを作成しました。新しい機能のテストケースを書きましょう。

val elements = listOf("a", "b", "c")

val result = ListExtension().getRandomElementOfList(elements)

assertTrue(elements.contains(result))

サードパーティのクラスを「拡張する」関数を定義することは非常に強力な機能であり、コードをより簡潔で読みやすくすることができます。


15. 文字列テンプレート

Kotlin言語の非常に優れた機能は

__String


s用のテンプレートを使用する可能性です。手動で


String

__sを連結する必要がないのでとても便利です。

val firstName = "Tom"
val secondName = "Mary"
val concatOfNames = "$firstName + $secondName"
val sum = "four: ${2 + 2}"


$ \ {}

ブロック内の式を評価することもできます。

val itemManager = ItemManager("cat__id", "db://connection")
val result = "function result: ${itemManager.isFromSpecificCategory("1")}"

16. KotlinとJavaの相互運用性

Kotlin – Javaの相互運用性はシームレスに簡単です。 __Stringを操作するメソッドを持つJavaクラスがあるとしましょう。

class StringUtils{
    public static String toUpperCase(String name) {
        return name.toUpperCase();
    }
}

今度はKotlinクラスからそのコードを実行したいのです。そのクラスをインポートするだけでよく、KotlinからJavaメソッドを問題なく実行できます。

val name = "tom"

val res = StringUtils.toUpperCase(name)

assertEquals(res, "TOM")

見てのとおり、KotlinコードのJavaメソッドを使いました。

JavaからKotlinコードを呼び出すのもとても簡単です。簡単なKotlin関数を定義しましょう。

class MathematicsOperations {
    fun addTwoNumbers(a: Int, b: Int): Int {
        return a + b
    }
}

Javaコードから

addTwoNumbers()

を実行するのはとても簡単です。

int res = new MathematicsOperations().addTwoNumbers(2, 4);

assertEquals(6, res);

Kotlinコードへの呼び出しは私たちには見えないことがわかります。

戻り型が

void

であるメソッドをjavaで定義すると、Kotlinでは戻り値は

Unit

型になります。

Java言語には、Kotlinコードで使用するときにエスケープする必要がある特殊な識別子(

is



object



in

、..)があります。たとえば、

object()

という名前のメソッドを定義できますが、これはjavaでは特別な識別子であるため、その名前をエスケープすることを忘れないでください。

fun `object`(): String {
    return "this is object"
}

それからそのメソッドを実行することができます:

`object`()


17. 結論

この記事ではKotlin言語とその主要機能について紹介します。それは、ループ、条件付きステートメント、そしてクラスの定義のような単純な概念を導入することから始まります。それから、拡張機能とnull安全のようないくつかのより高度な機能を示します。

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/core-kotlin[GitHubプロジェクト]にあります – これはMavenプロジェクトなので、簡単にできます。そのままインポートして実行します。