Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
【Kotlin】【Android】Null安全でぬるぽに立ち向かう
Search
masanori_msl
July 09, 2016
Programming
2
2.4k
【Kotlin】【Android】Null安全でぬるぽに立ち向かう
2016.07.09 Kansai.kt #1 用資料です。KotlinのNull安全について調べたことをまとめています。
masanori_msl
July 09, 2016
Tweet
Share
More Decks by masanori_msl
See All by masanori_msl
WPFで印刷しよう!
masui_masanori
1
790
Programming ASP.NETCore を推したい話
masui_masanori
0
190
C#erがTypeScriptでフロントエンドに挑戦している話
masui_masanori
0
210
ASP.NET CoreやTypeScriptの力を借りてレガシー寄りの環境に立ち向かいたかった話
masui_masanori
1
150
やっぱりわからんTaskの話
masui_masanori
0
98
AzurePipelinesでコンティニュアスにインテグレーションしたい
masui_masanori
0
1.3k
Razorに触れてみた
masui_masanori
0
57
ASP.NET Coreに入門した話
masui_masanori
0
240
Compare Java's 'var' with C#'s 'var'.
masui_masanori
0
1.3k
Other Decks in Programming
See All in Programming
MLOps in Mercari Group’s Trust and Safety ML Team
cjhj
1
110
DjangoNinjaで高速なAPI開発を実現する
masaya00
0
500
Unlocking Python's Core Magic
leew
0
120
"noncopyable types" の使いどころについて考えてみた
andpad
0
140
実践Dash - 手を抜きながら本気で作るデータApplicationの基本と応用 / Dash for Python and Baseball
shinyorke
2
260
tsconfig.jsonの最近の新機能 ファイルパス編
uhyo
6
1.6k
PHPを書く理由、PHPを書いていて良い理由 / Reasons to write PHP and why it is good to write PHP
seike460
PRO
5
450
利用者視点で考える、イテレータとの上手な付き合い方
syumai
4
220
文化が生産性を作る
jimpei
3
550
学生の時に開催したPerl入学式をきっかけにエンジニアが組織に馴染むために勉強会を主催や仲間と参加して職能間の境界を越えていく
ohmori_yusuke
1
130
CSC509 Lecture 02
javiergs
PRO
0
160
"Swarming" をコンセプトに掲げるアジャイルチームのベストプラクティス
boykush
2
230
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
43
6.5k
A better future with KSS
kneath
237
17k
Art, The Web, and Tiny UX
lynnandtonic
296
20k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
7
290
Web Components: a chance to create the future
zenorocha
310
42k
How STYLIGHT went responsive
nonsquared
95
5.1k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
Docker and Python
trallard
40
3k
Mobile First: as difficult as doing things right
swwweet
222
8.8k
Large-scale JavaScript Application Architecture
addyosmani
509
110k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
7
570
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
1
280
Transcript
【Kotlin】【Android】 Null安全でぬるぽに立ち向かう 2016.07.09 @Kansai.kt
Who? Twitter: @masanori_msl vaguely: http://mslgt.hatenablog.com/ SearchWakayamaToilet: https://play.google.com/store/apps/details? id=jp.searchwakayamatoilet Name: Masui
Masanori
はじめに Kotlinのいいところ
はじめに Null安全
はじめに Kotlinを使えば、 ぬるぽ(NullPointerException)に サヨナラできる ∩( ・ω・)∩ばんじゃーい
はじめに 本当に?
はじめに 調べてみた
Null許容(Nullable) Kotlinでは、変数をNullにすることが可能か そうでないかが区別される。 var nullableText: String? = null ▪Null許容型(Nullable Type)
▪非Null許容型(Non-Null Type) var notNullableText: String = null // ※コンパイルエラー
Null許容(Nullable) 非Null許容型の変数に、Null許容型の変数を代入 するには、後者がNullでないことを保証する必要 がある。 var nullableText: String? = "Not null"
var notNullableText: String = nullableText!! // OK ※ ではこれは...? var nullableText: String? = null var notNullableText: String = nullableText!!
Null許容(Nullable) KotlinNullPointerExceptionが発生する
Null許容(Nullable) Kotlinではlateinitを付けることで、変数の初期化 のタイミングを変更できる。 … この変数を初期化せずに使うと ? lateinit var lateinitNotNullableText: String
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) var notNullableText: String = lateinitNotNullableText var length = lateinitNotNullableText.length }
Null許容(Nullable) UninitializedPropertyAccessExceptionが発生 する lateinit var lateinitNotNullableText: String override fun onCreate(savedInstanceState:
Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) var notNullableText: String = lateinitNotNullableText // NG ※ var length = lateinitNotNullableText.length // NG ※ }
Null許容(Nullable) Javaのコード上ではNull許容型・非Null許容型の 制限が強制されない。 MainActivity.kt NotNullClass.java - 省略 - public String
getText(){ return null; // 実行可能 } - 省略 - val notNullableClass = NotNullableClass() val notNullableText: String = notNullableClass.getText() }
Null許容(Nullable) IllegalArgumentExceptionが発生する Java側からKotlinのメソッドを呼ぶときの引数 (非Null許容)にNullを渡そうとする場合は、 @NonNullと同じく警告は表示されるが実行自体 は可能。
Kotlinのいいところ? Kotlinを使うだけで、 ぬるぽにサヨナラできる
Kotlinのいいところ? Kotlinを使うだけで、 ぬるぽにサヨナラできる
Kotlinのいいところ Kotlinを使うと、 ぬるぽを発生させない設計が しやすくなる
Kotlinのいいところ ΩΩΩ < ナ、 ナンダッテー!!
Kotlinに力を借りて、 ぬるぽに立ち向かう ここから本題
Sample SearchWakayamaToilet https://github.com/masanori840816/SearchWakayamaToilet
ぬるぽを無くすには? ぬるぽが嫌なら、 コードからNullを 無くしてしまえばいいじゃない
非Null許容型にする Nullにならないことを保証できる変数は、Nullを 許容しないことでコードをシンプルにできる。 class MainActivity : AppCompatActivity() { var notNullableText:
String = "" // Nullを代入しない override fun onCreate(savedInstanceState: Bundle?) { - 省略 - var length = NotNullableText.length // Nullチェックが不要 } } 引数にも適用可能だが、特にコールバックで呼ば れた時に本当にNullが渡されないか確認が必要。
lateinit Nullにならないことは確実だが、宣言時に値が入 れられない変数ではlateinitを使う。 class MainActivity : AppCompatActivity() { lateinit var
notNullableClass: NotNullableClass // 後で初期化 override fun onCreate(savedInstanceState: Bundle?) { - 省略 - // 宣言時に値が入れられない場合も非Null許容型にできる notNullableClass = NotNullableClass() } }
非Null許容型にする 例えばMVCにおけるControllerなど、 Nullにできない変数も非Null許容型にする。 プログラム全体が動作しなくなる変数がNullの場 合は、下手に延命するよりエラーなどでアプリを 終了させる方が良い、ということ。
Null許容型を使う コールバックメソッドの引数など、 全部非Null許容型にするのは難しい。 ↓ Null許容型を安全に使いたい
Nullチェック class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ - 省略 - var nullableText: String? = “Not null” var length = -1 if(nullableText != null){ // Nullチェック // Nullをチェックしているので // ”!.”を使っても安全にlengthを実行可能 length = nullableText!.length } } } 通常のNullチェック
Nullチェック class MainActivity : AppCompatActivity() { val nullableText: String? =
“Not null” override fun onCreate(savedInstanceState: Bundle?) { - 省略 - var length = -1 if(nullableText != null){ // Nullチェック // Nullで無いことが保証されるので // 非Null許容の変数と同じように扱うことが可能 length = nullableText.length } } } valを使ってimmutableにできる場合
Nullチェック class MainActivity : AppCompatActivity() { val nullableText: String? =
“Not null” override fun onCreate(savedInstanceState: Bundle?) { - 省略 - var length = -1 if(nullableText == null){ // Nullチェック return // Nullなら以下の処理をスキップ } // 非Null許容の変数と同じように扱うことが可能 length = nullableText.length } } これもOK
Nullチェック class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ - 省略 - var nullableText: String? = “Not null” var length = -1 if(nullableText != null){ // Nullチェック // Nullで無いことが保証されるので // 非Null許容の変数と同じように扱うことが可能 length = nullableText.length } } } ローカル変数ならmutableな変数でもOK
Nullチェック 一度値を入れた後は値を変更しない変数 メソッドに引数として渡される値 ※引数は全てImmutable 使いどころ
?演算子 Null ” 許容型の変数では、 ?.”を使うことで安全にア クセスできる。 class MainActivity : AppCompatActivity()
{ override fun onCreate(savedInstanceState: Bundle?) { - 省略 - val nullableText: String? = “Not null” // nullableTextならNullが // それ以外はnullableText.lengthの値が入る var length = nullableText?.length } }
?演算子 ”?.”を使ったチェーンメソッド class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState:
Bundle?) { - 省略 - val nullableText: String? = “Not null” // nullableText、lengthのどちらかがNullならNullが入る var lengthText = nullableText?.length?.toString() } }
疑問 この2つのコード、結果は同じ。 var nullableText: String? = “Not null” var nullableNum1:
Int? = null var nullableNum2: Int? = null // Code 1 if(nullableText != null){ nullableNum1 = nullableText.length NullableNum2 = nullableText.length } // Code2 nullableNum1 = nullableText?.length nullableNum2 = nullableText?.length 実行速度に違いはある?
疑問 調べてみた
計測 class MainActivity : AppCompatActivity() { lateinit var logger: TimingLogger
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // ログの取得開始. logger = TimingLogger("KtTimingLogger", "Code") // getLengthOfCode1()またはgetLengthOfCode2()を実行 // 測定を終了してログ出力する. logger.dumpToLog() } android.util.TimingLoggerを使って計測
計測 fun getLengthOfCode1(){ // Code1の検証. var nullableText: String? = "not
null" var nullableNum1: Int? = null var nullableNum2: Int? = null for(i in 0..1000000) { if (nullableText != null) { nullableNum1 = nullableText.length nullableNum2 = nullableText.length } } logger.addSplit("Code1おしまい") }
計測 fun getLengthOfCode2(){ // Code2の検証. var nullableText: String? = "not
null" var nullableNum1: Int? = null var nullableNum2: Int? = null for(i in 0..1000000) { nullableNum1 = nullableText?.length nullableNum2 = nullableText?.length } logger.addSplit("Code2おしまい") }
結果 Code1 24ms Code2 24ms [検証環境] Android Studio ver. 2.1.2
[端末] Nexus 9 (Emulator) [OS] Android N
結果 • “if(x != null)”でチェックする場合も?演算子を使 う場合も、少なくとも今回の検証ではほぼ差が 見られなかった。 • 状況に合わせてよりシンプルに書ける方を選択 するのが良さそう。
Elvis演算子 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ - 省略 - var nullableText: String? = null // nullableTextがNull ” の場合のみ ?:”の右の値を代入する nullableText = nullableText?: “Null ” でした // 今回はローカル変数なので、もう一度nullableTextに // Nullチェック不要を入れるまではNullチェック不要 } } ”?:”を使うことで、変数がNullの場合のみ値を代入 できる。
Elvis演算子 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)
{ - 省略 - var nullableText: String? = null // 変数がNullなら以降の処理をスキップ nullableText?: return - 省略 - } } ”?:”を使うと変数がNullの場合はreturnする、とい うことも可能。
まとめ • Kotlinはぬるぽを無くしてくれるわけではない。 • ぬるぽを無くすにはコールバックの引数などア プリの動きをより詳しく把握する必要がある。 • Kotlinの豊富な機能でハッピーな開発ライフを!
参考 5.4 NULL 安全 - プログラミング言語Kotlin 解説 16 日目:ぬるぽとの別れ -
Kotlin Advent Calendar 2012 (全部俺) Reference - Kotlin Programming Language 30分で覚えるKotlin 文法 - Qiita https://kotlinlang.org/docs/reference/ https://sites.google.com/site/tarokotlin/chap5/sec54 http://kotlin.hatenablog.jp/entry/2012/12/16/001635 http://qiita.com/k5n/items/cc0377b75d8537ef8a85 http://qiita.com/datsnet/items/1b868ced7c2fa8b4dcb0 処理時間の計測をAndroid で簡単に行う - Qiita
Credit Google Noto Fonts Main Page: License: Material
icons Main Page: License: https://www.google.com/get/noto/ SIL Open Font License (OFL) https://design.google.com/icons/ CC-BY License
Enjoy Kotlin Life :)