##▼null
nullとは・・・オブジェクトの参照を持たないことを意味する値
オブジェクトの参照とはなんぞや??
Kotlinでは値=オブジェクト。
値(オブジェクト)は、コンピュータのメモリに格納されることで保持できている。
ここに割り当てられてますよーという住所のようなものがオブジェクトごとに与えられてる。
この住所のようなものを「メモリアドレス」という。
メモリアドレスという一つの住所に、一つのオブジェクトが入っている状態をさす。
変数は、このメモリアドレスを参照して格納されてる値(オブジェクト)を引き出すための仕組みなので、
変数にオブジェクトの参照が設定されていない状態を「null」という
Kotlinでは原則、「nullを許容しない(null禁止)」設定になっているため、以下のようにfooにnullを代入しようとするとエラーが起こる
var foo:String = "foo"
foo = null //エラー
逆にあえてnullを許容したいときには型の後ろに「?」をつけてあげる
var foo:String? = "foo"
foo = null
こういうnullを許容してあげることを「nullable型(null許容型)」という
※他の型でも使える
そもそもKotlinでnullを禁止にしたのは、nullがあることでエラーを起こす可能性が高まるから。
そのため、禁止になっているのに使えるようにする場合には注意点がある。
###●非null型をnullable型に代入するとボクシング(暗黙的な型変換)が起きる
例)変数aを非null型bとnullable型cにそれぞれ代入
補足:同じ値を持つことを同値、同じオブジェクトを持つことを同一といい、
同値の比較には「==」、同一の比較には「===」の演算子を使う
var a:Int = 1000
var b:Int = a
var c:Int? = a
println(a == b) //結果:true
println(a === b) //結果:true
println(a == c) //結果:true
println(a ==== c) //結果:false
この場合、aとbは同じ値で同じオブジェクトのため、trueになる。
(aとbの値は1000、aとbのオブジェクトはどちらも非null型)
だけど、cに代入した場合、値は同じ1000でtrueになっても、オブジェクトが違っている。
aのオブジェクトは非null型に対して、cはnullable型。
ここが違うため、オブジェクトはfalseになっている。
これは、非null型をnullable型に代入するとボクシング(暗黙的な型変換)が起こるという現象になっている。
###●nullable型を非null型に代入することはできない
例)非null型のStringにnullable型を代入してもエラーになるが、Any型ならどうなるか?
補足:Any型:すべての任意のデータ型を代入できる
var foo1:String? = "foo"
var foo2:String = foo1 //エラー
var a1:String? = "a"
var a2:Any = a1 //エラー
結果としては、Any型でもエラーになる。
Any型もnullを許容しないので、エラーになっている。
Any?として、nullable型に変更すればエラーはでない。
Any型は全ての任意のデータ型を代入できるが、詳しくいうと
「Any型を指定すると任意の非null型を代入できる」
また、「Any?型を指定すると、任意のnull型を含む型を代入できる」
###●nullable型のメンバにアクセスする場合は、「?.(セーフコール演算子)」を使う
例)lengthプロパティにアクセスしたい
補足:
メンバ:オブジェクトに定義されているフィールド変数やメソッド
lengthプロパティ:文字列の長さや配列の要素数を取得する
var a:String? = "foo"
println(a?.length) //結果:3
var b:String? = null
println(b?.length) //結果:null
nullable型の変数をlengthプロパティにアクセスして表示させたい場合には、「?.(セーフコール演算子)」というものを使う。
これを使うことによって、エラーが起きることなくアクセスさせられる。
また、これでnullにアクセスした場合には、エラーとはならず、nullが返ってくる。
nullを返すのではなく、既定値を設定したい場合には、「?:」演算子を使う
var b:String? = null
println(b?.length ?: 0) //結果:0
nullable型を強制的に非null型にしたいときは「!!」演算子を使う
※ただし、これはnullable型を非null型にするときにのみ利用するため、もしaが非null型であった場合にはエラーが発生するので注意!
var a:String? = "foo"
println(a!!.length) //結果:3