ヘリオトロープ色が好きなKURAMOTOです。エム・フィールドのES事業部で金融案件をメインにSEをしています。ヘリオトープというのは、夏から秋にかけて咲く紫の花です。和名では「香水草」や「匂ひ紫」と言われ、甘い香りがするので香水の原料にもなっているそうです。
さて、少し前に「Kotlin」について勉強したので、本記事では、私自身の備忘も兼ねて「Kotlinを勉強してわかったこと」というお題目で色々と書いてみようと思います。
そもそも「なぜKotlinなのか?」ですが、私がKotlinを学ぼうと思った理由は「今までJava開発をメインにしてきたので、Kotlinは学習コストが低い」からです。
「将来性がある」とか「様々なサービスで利用されている・需要が高い」という理由であれば、Kotlinに限らずGo言語などもありだと思うのですが、Javaをメインに開発してきたため、個人的にGoを含むC系言語は学習難易度が物凄く高いイメージがあります。
その点、KotlinはJavaとの相互互換を謳っていて文法がJavaベースのため、Javaプログラマーにとっては学びやすく、乗り換えやすい言語だと思います。
実際に私が勉強して感じたのは、Javaの知識がある人であれば、Kotlinの学習コストは、圧倒的に低いということです。(決してKotlinがゼロベースからの学習に向いていない、というわけではないです。)
Androidのアプリ開発がメインのKotlinですが、サーバサイドの開発も可能なため「スマホアプリ開発が目的じゃないんだけどなぁ」というサーバーサイドのエンジニアにもKotlinの知識は役立つと感じました。
「Javaの知識があれば学習コストが低いということは、文法は似たり寄ったりなのか?」という疑問が浮かぶ人もいるかも知れません。文法のベースは確かにJavaですが、実際は割と異なる部分があります。
ここからは、Kotlinを学習するにあたって、どういうところがJavaと違っているのかを実例で紹介していきたいと思います。
全部の違いの説明は出来ないので、特に違いが顕著な4つの部分をピックアップしてご説明します。
■目次
1.変数の宣言
2.nullの扱い
3.演算子、制御構文
4.関数
■まとめ
1. 変数の宣言
まず最初は「変数の宣言」についてです。
Javaでは変数の宣言をする時は「アクセス修飾子 データ型 変数名 = 初期値」の順で宣言しますが、Kotlinでは「アクセス修飾子 var 変数名:データ型 = 初期値」の順で宣言します。
【Java】
public String javastr = “Java”
【Kotlin】
public var kotlinstr: String = “Kotlin”
「var」というキーワードを使ってるあたりが、Javaよりも一昔前のC#やjavascriptに近い感じがします。ちなみにKotlinでは文の末尾にセミコロンは不要です。
データ型については、Javaとそれほど変わらない感じですが、Kotlinにはプリミティブ型はなく、全てがオブジェクトになっています。
ですのでJavaのようにintとIntegerを使い分ける必要はなく、常にIntと書けば大丈夫な仕組みになっています、便利。
またKotlinには「型推論」という機能があるため、初期値があればデータ型の宣言は省略することが可能です。(これは古いJavaにはありませんでした…がJava10からローカル変数に対してJavaでもvarを使った型推論ができるようになったので、Java10以降の環境で開発を行っている方には割と馴染みがあるかもしれないですね)
「アクセス修飾子」についても、KotlinとJavaで次のような違いがあります。
・internalという修飾子がある(Javaには存在しない)
・アクセス修飾子なし(デフォルト)はpublic扱い
(Javaのデフォルトはパッケージプライベートだが、Kotlinには同等のものは存在しない)
・protectedは自クラスと継承したサブクラスからのみ参照可能
(Javaは同一パッケージ内であれば参照可能だが、Kotlinは許容していない)
・privateはトップレベルでの宣言が可能(Javaでは不可能)
Javaと比べると、キーワードごとのスコープが明確になってるような気がします。しかしJavaと同じキーワードでも、スコープが異なるものがあるので慣れないうちは注意が必要です。
定数の場合も変数の時とほぼ同じですが、使うキーワードが「val」または「const val」になります。「val」の場合はトップレベル、ローカルどちらでも宣言できますが「const val」はトップレベルでのみ宣言できます。
2. nullの扱い
次に「nullの扱い」についてです。
なんとKotlinはJavaと異なりnullを「許容していない」のです!!
素晴らしい!!!
…と言っても全面的に非許容なわけではなく、原則非許容というだけです。
原則非許容の理由は、KotlinはJavaよりも安全性を高めた設計の言語となっているためです。nullを使いたい場合には、null許容型で変数を宣言してあげれば、ちゃんとnullを扱うことができます。どのように宣言するかというと「var str: String?」のようにデータ型の後ろに「?」を付けてあげるだけです。
個人的には、nullを許容するものを明確にする方が、万が一、NullPointerExceptionが発生しても原因の箇所を特定しやすそうなので良いなと思っています。
ただしnull許容型を扱う際には「null許容型の変数をnull非許容型の変数に代入することはできない」など、いくつか注意する点があります。
Javaに慣れ親しんでいると、この辺りはつい、うっかりやっちゃいそうですが、そこはKotlinがコンパイル時にエラーを吐いてくれるので安心です。
3. 演算子、制御構文
続いて「演算子、制御構文」もJavaと異なる点があるので、まずは演算子からご説明します。
四則演算などの基本的なものはJavaを始め他のプログラミング言語と同じです。
比較演算子については、よく使われる「==、<、>、<=、>=、!=」の他に、「===、!==」というものがKotlinにはあります。
これは「同一のオブジェクトか、否か」を評価する時に使われます。
ここが少しややこしくて「===、!==」はJavaで言うところの「==、!=」であり、Kotlinの「==、!=」はJavaで言うところのequalsメソッドに該当します。(多分)
このあたりも慣れないと、等価比較したつもりが間違った使い方をして痛い目を見るかもしれないですね。
他には範囲演算子なるものもあります。
「m..n」というふうに記述することで、mからnまでの範囲を表現することができます。これはJava8以降のrangeClosedメソッドに該当しますが、for文などで範囲指定する際「..」で済ませられる分、生産性も可読性もかなり良いように思います。
次は制御構文についてです。
Kotlinでも条件分岐は、もちろんifを使います。ただしif「文」ではありません、if「式」であることに注目です。
式なので値を返すことができますが、ifを式として用いた場合は必ず何かしらの値を返す必要があるので、elseを省略することができないことに注意が必要です。
val a = 10
var str = if (a <= 5 ) {
"message1"
} else if (a <= 10) {
"message2"
} else {
"message3"
}
println(str) // "message2"
KotlinにはJavaにある「switch文」は存在しません。ではどうすればいいのか?switch文の代わりにwhen式を使います。
はい、こちらも式なのでif式と同様に値を返すことが可能で、その場合はelseが必須となります。
val a = 65
var str = when (a) {
in 51..100 -> "message1"
in 1..50 -> "message2"
else -> "message3"
}
println(str) // "message1"
他にもループ処理で使う構文(forやwhileなど)も、もちろんありますが、Javaと比べて書き方がかなりシンプルで分かりやすくなっています。
for文を例に挙げると、Javaの場合
for(int i = 0; i <= 9; i++){
System.out.println(i);
}
と書くところを、Kotlinでは
for(i in 0..9) println(i)
のように{}を省略した形で1行で済ませられますし、もちろんJavaのようなブロックで書くこともできます。
4. 関数
Javaの“メソッド”に当たるものをKotlinでは“関数”と呼び、「fun」キーワードを使って定義を行います。Kotlinの関数は「クラス内にしか定義できない」なんてことはなく、トップレベルで定義することができます。(この辺りはJavaScriptの関数定義と同じですね)
書き方は以下のようになります。
fun 関数名 (仮引数1: 引数のデータ型,仮引数2: 引数のデータ型,...): 戻り値のデータ型 {
処理
}
仮引数と戻り値のデータ型の宣言は必須ですが、戻り値がない場合、Kotlinでは「Unit」キーワードを指定します。データ型の宣言は必須と言いましたが、例外としてUnit型だけは記述を省略することが可能です。また、仮引数には関数を呼び出した際に引数が省略された時に使われるデフォルト値を設定することができます。デフォルト値を設定したい時は「仮引数: 引数のデータ型 = デフォルト値」で記述します。
関数を呼び出す時には名前付き引数を使うことができます。
名前付き引数を使うことによって「引数の数が増えても、どの引数にどの値を渡すのかを明示的に指定できるので分かりやすい」「定義時の引数の順番を気にする必要が無いので使いやすい」といったメリットがあります。
ただし注意点として名前付き引数は実引数の後ろに記述する必要があります。
関数に関しては複数の戻り値や高階関数、ラムダ式と匿名関数なども使えるので、javascriptやPython辺りをやっていたら馴染みがあると思います。(私は業務で使ったことがないのでPythonの勉強の時もそうでしたが、この辺りは苦手意識が強いです笑)
■まとめ/さいごに
以上、JavaとKotlinの違いが顕著な4点をピックアップしてご説明しました。ずらずらーっと書いてみましたが、こうやって見るとKotlinはJavaをベースにと言いつつも、javascriptやPythonなど他の言語の要素を沢山取り入れてるのが分かります。
Kotlinにはコードを簡潔に書くための仕組みが、今回挙げたもの以外にも多数用意されています。私のようにJavaしか書いていなくて、他の言語に抵抗がある方は、IntelliJ IDEAを使ってみるのはいかがでしょうか?
IntelliJ IDEAにはJavaのソースコードをKotlinのコードに変換する機能があるので、JavaからKotlinに変換すると、どのように変わるのか見比べてることができ、見比べると理解しやすいと思います。
「とりあえず触ってみたいけど開発環境を用意するのが面倒」という人は、簡単なものであれば、Kotlinの公式サイト上で実際にコードを書いて動かすことができますので、そちらを試してみるのも良いかも知れません。(私はKotlinを勉強していた時は、公式サイト上であれこれ実際に書いて色々試してました。)
Javaを通常の業務で使っている私には、KotlinはJavaの文法をベースにしているだけあって基礎的な部分は割とすんなり入ってきましたし、それ以外の部分についても「あーJavaだとこう書くけど、Kotlinだとこう書くのかー」という感じで対応関係が把握できれば、それなりに理解しやすかったです。
「ずっとJavaしかやってなくて、今さら他の言語の勉強もなぁ…」という人が、この記事を読んで少しでもKotlinの勉強してみようかなと興味を持ってもらえたら幸いです。
ちなみに、当社は資格補助制度が充実しており、各種資格に合格すると試験料の免除だけでなく、毎月の手当が出る資格もあるので、私もそろそろ新しい資格取得に励みたいと思っています。
あなたもエム・フィールド グループで働いてみませんか?
エム・フィールドグループは事業拡大に伴い、一緒に働く仲間を通年で募集しています。
データサイエンティスト、Webアプリケーションエンジニア、AWSエンジニア、ITコンサルタント、サービス運用エンジニアなどさまざまな職種とポジションで、自分の色を出してくださる方をお待ちしています。ご興味のある方は、採用サイトもご覧ください。
●エム・フィールド採用ページ
-メンバーインタビュー (1日の仕事の流れ/やりがい/仕事内容)
-プロジェクトストーリー (プロジェクトでの実績/苦労エピソード)
●募集ページ
プリセールス/ エンジニア/ クリエイター/ データサイエンティスト /営業・コンサルタント /コーポレート /サービス企画 /教育担当