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
820
Programming ASP.NETCore を推したい話
masui_masanori
0
200
C#erがTypeScriptでフロントエンドに挑戦している話
masui_masanori
0
210
ASP.NET CoreやTypeScriptの力を借りてレガシー寄りの環境に立ち向かいたかった話
masui_masanori
1
170
やっぱりわからんTaskの話
masui_masanori
0
100
AzurePipelinesでコンティニュアスにインテグレーションしたい
masui_masanori
0
1.4k
Razorに触れてみた
masui_masanori
0
61
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
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.3k
cmp.Or に感動した
otakakot
3
230
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
170
RubyLSPのマルチバイト文字対応
notfounds
0
120
Jakarta EE meets AI
ivargrimstad
0
200
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
630
イベント駆動で成長して委員会
happymana
1
340
色々なIaCツールを実際に触って比較してみる
iriikeita
0
340
Less waste, more joy, and a lot more green: How Quarkus makes Java better
hollycummins
0
100
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
260
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
200
Featured
See All Featured
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Why Our Code Smells
bkeepers
PRO
334
57k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Intergalactic Javascript Robots from Outer Space
tanoku
269
27k
Automating Front-end Workflow
addyosmani
1366
200k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
109
49k
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 :)