はじめに
- 当記事は下記の環境にて動作を確認しています。
- Android Studio 3.0
- Kotlin 1.1.51
- compileSdkVersion 25,及び26
- 当記事はKotlin Advent Calendar 2017の14日目の記事です。
- Javaしか書いたことない人でもわかりやすいように書いた…つもりです。
Null Safetyとは
すでに「Null Safety?知ってるよ!」な方は飛ばしてください。
KotlinはJavaと違い基本的にnullは使用できません。
というのも、基本的にオブジェクトがnon nullableだからです。
例えば、下記のコードはエラーになります。
val sampleStr: String = "Kotlin"
println(sampleStr)
sampleStr = null
では、nullを使用したい場合はどうすればいいのでしょうか?
答えは下記のコードの通りです。
var sampleStr: String? = "Kotlin"
println(sampleStr)
sampleStr = null
println(sampleStr)
String?型はString型とはまったく異なるクラスです。
これは下記のコードによって確かめることができます。
val sampleStr1: String = "Kotlin"
var sampleStr2: String? = null
println(sampleStr1 is Any)
println(sampleStr2 is Any)
Anyについては、
JavaプログラマがKotlinでつまづきがちなところ
が詳しいです。
ホントにNull Safetyなの?
Kotlinではnullableかどうかが型ではっきりとわかるということがわかりました。
では、コンパイルされるときにnullableかどうかがはっきりわかるので、
これでもうNullPointerExceptionとはお別れですね!うーんスッキリ!
…というわけにも行きませんでした。
下記コードをご覧ください。
fun <T : View> View.bindView(@IdRes id: Int): Lazy<T> = lazy {
findViewById(id) as T
}
class SampleView : FrameLayout{
constructor(context: Context?) : super(context)
constructor(context: Context?,
attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int) : super(context, attrs, defStyleAttr)
constructor(context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
private val profileImageView: ImageView by bindView(R.id.profile_image_view)
private val titleTextView : TextView by bindView(R.id.title_text_view)
private val userNameTextView: TextView by bindView(R.id.user_name_text_view)
// (以下略)
なんと、上記コードはコンパイルを通ってしまいます。
何が問題かというと…。
実はfindViewByIdはnullableです。
的確にIDを指定していれば問題ないのですが、間違った値を入れてしまうと…。
あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛あ゛!(絶叫)
ということになります。
ホントはNull Safetyじゃないの?
本記事では、ここからどのようにNullPointerExceptionを起こせるか実験しつつ記載しようと思ったのですが、
実は2017年11月10日現在、既にAndroid SDK側で対応されておりました。
アドベントカレンダー2017、明日はkamedon39さんです。