Java開発者が勉強したJava vs Kotlin① 基礎文法(変数とNull処理)
はじめに
ひさしぶりの投稿です!
去年から、JavaとSpringを用いたプロジェクトに参加し、3月末にプロジェクト終わりますが、
Kotlinに興味を覚え始めました。まだ、Javaの中でもマルチスレッド関連の知識は足りてないため、KotlinのCoroutineのような非同期処理までまとめることは難しいですが、自分なりにオンライン講座から勉強した内容をまとめ、シェアしたいと考えました。
変数
var & val
int number = 1;
final int number2 = 2;
int onlyDeclare;
var number = 1
val number2 = 2
var onlyDeclare:Int
Javaの場合、データ型の指定が必須だが、
Kotlinの場合、TypeScriptのようにコンパイラから型推論をする。
var
は変数、val
は定数を表す。
また、初期化をしない場合は型指定をする必要があり、型指定はTypeScriptの似ている。
基本型 & 参照型
int number = 1;
Integer number2= 1;
var number: Int = 1
Javaの場合、int
は基本型、Integer
は参照型である。
Integer
のようなクラスはラッパークラスで、Java
によりプリミティブ型のデータを包んだり、オブジェクトをまた基本型に変換する。
しかし、Kotlinは基本型と参照型を分けて宣言せず、場合によっては内部で自動的にプリミティブ型として最適化される。
nullable
Integer number= 1;
number = null;
var number: Int? = 1
number = null
Javaの場合、Integer
は参照型である。そのためnullを格納することができますが、
Kotlinは基本的には変数にnullを格納することができない。
nullを格納するためには?
を付け、nullable
として宣言する必要がある。
instance
Human human = new Human("hoge");
var human = Human("hoge")
Javaの場合、インスタンスを作成する際にnew
演算子を使用する。
Kotlinでは、インスタンスを作成する際にnew
を使わない。
kotlinのNull処理
nullチェック1
先ほどのnullableを利用し、nullチェックをしてみる。
public boolean startsWithR1(String str) {
if (str == null) {
throw new IllegalArgumentException("nullが入りました。");
}
return str.startsWith("R");
}
fun startWithR1(str:String?): Boolean{
if (str == null) {
throw IllegalArgumentException("nullが入りました。")
}
return str.startsWith("R")
}
nullチェック2
public Boolean startsWithR2(String str) {
if (str == null) {
return null;
}
return str.startsWith("R");
}
fun startWithR2(str:String?): Boolean?{
if (str == null) {
return null
}
return str.startsWith("R")
}
nullチェック3
public boolean startsWithR3(String str) {
if (str == null) {
return false;
}
return str.startsWith("R");
}
fun startWithR3(str:String?): Boolean?{
if (str == null) {
return false
}
return str.startsWith("R")
}
SafeCall
val word : String? = "Ramen"
println(word.length)
nullable演算子が入ったStringの場合、println(word.length)
を出力する場合、
赤い下線が表示され、コンパイルに失敗する。
wordがnullになる可能性があり、NPEが発生する可能性があるからだ。
その場合は?.
という演算子を使用する。
val word : String? = "Ramen"
println(word?.length) //5
word = null
println(word?.length) //null
wordがnullではない場合、後ろにあるlength
が呼び出され、
nullの場合、そのままnullになるため、NPEを事前に防ぐことがわかる。
まるで、JavascriptのOptional Chainingと似ている。
エルビス演算子
val left: String? = null
println(elvis?:right) // right
?:
はエルビス演算子という。エルビス演算子の左がnullである場合、Elvis演算子の右の値が格納される。
これから、Safecallとエルビス演算子を利用し、先ほどのNullチェック1,2,3をリファクタリングしてみる。
nullチェック1(Clean)
fun startWithR1(str:String?): Boolean{
if (str == null) {
throw IllegalArgumentException("nullが入りました。");
}
return str.startsWith("R")
}
fun startWithR1(str :String?): Boolean{
return str?.startsWith("A")
?: throw IllegalArgumentException("nullが入りました。")
}
nullチェック2(Clean)
fun startWithR2(str:String?): Boolean?{
if (str == null) {
return null
}
return str.startsWith("R")
}
fun startWithR2(str:String?): Boolean?{
return str?.startsWith("R")
}
nullチェック3(Clean)
fun startWithR3(str:String?): Boolean?{
if (str == null) {
return false
}
return str.startsWith("R")
}
fun startWithR3(str:String?): Boolean?{
return str?.startsWith("R"):false
}
ノットヌルアサーション演算子
例えば、絶対にある値にnullが入らない場合、
エルビス演算子とsafe callで処理を行うことはリソースを無駄にする可能性がある。
その際には!!.
演算子を使用する。
!!.
はKotlinのコンパイラに左の値はNullではありません。チェックをしないでくださいと意味だ。
val str = "Ramen"
fun startWithR3(str:String?): Boolean?{
return str!!.startsWith("R"):false
}
感想
フロントエンドに興味があるため、JavaScriptとTypeScriptを勉強したことがありますが、
Kotlinって結構TypeScriptと似ていてて、Pythonのように;が要らなくて楽でした。
特にNull-Safetyで、条件分岐を入れずに簡単な演算子でNullチェックを行うことができ、
便利でした。さすが流行ってるには理由がある!
Discussion