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.5k
【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
900
Programming ASP.NETCore を推したい話
masui_masanori
0
230
C#erがTypeScriptでフロントエンドに挑戦している話
masui_masanori
0
220
ASP.NET CoreやTypeScriptの力を借りてレガシー寄りの環境に立ち向かいたかった話
masui_masanori
1
210
やっぱりわからんTaskの話
masui_masanori
0
120
AzurePipelinesでコンティニュアスにインテグレーションしたい
masui_masanori
0
1.4k
Razorに触れてみた
masui_masanori
0
77
ASP.NET Coreに入門した話
masui_masanori
0
260
Compare Java's 'var' with C#'s 'var'.
masui_masanori
0
1.3k
Other Decks in Programming
See All in Programming
データベースエンジニアの仕事を楽にする。PgAssistantの紹介
nnaka2992
9
4.4k
Qiita Bash
mercury_dev0517
1
170
List とは何か? / PHPerKaigi 2025
meihei3
0
610
マルチアカウント環境での、そこまでがんばらない RI/SP 運用設計
wa6sn
0
700
Boost Your Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
1k
自分のために作ったアプリが、グローバルに使われるまで / Indie App Development Lunch LT
pixyzehn
1
150
SQL Server ベクトル検索
odashinsuke
0
160
Code smarter, not harder - How AI Coding Tools Boost Your Productivity | Webinar 2025
danielsogl
0
110
PHPのガベージコレクションを深掘りしよう
rinchoku
0
260
Devin入門と最近のアップデートから見るDevinの進化 / Introduction to Devin and the Evolution of Devin as Seen in Recent Update
rkaga
9
4.5k
Kamal 2 – Get Out of the Cloud
aleksandrov
1
160
AIコーディングワークフローの試行 〜AIエージェント×ワークフローでの自動化を目指して〜
rkaga
2
3k
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
7
640
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
30
1.1k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
380
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
18
1.1k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
12
1.4k
GraphQLとの向き合い方2022年版
quramy
45
14k
Visualization
eitanlees
146
16k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.6k
Six Lessons from altMBA
skipperchong
27
3.7k
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 :)