1. null ni fukaku hairu
String? o miru to, shoshinsha no nou wa yoku “null ni naru kamoshirenai = ?. o tsukete tsugi e susume ba ii” to yomikomi ga chi desu. Demo program design ni tott e yaku ni tatsu no wa betsu no yomikata desu: String? wa sono function/field no sakusha ga okuru yakusoku de ari, “chi ga nai koto” ga futsuu de, kitai sareta kekka da to iu koto. Koko kara ga “oton a no seikatsu” desu: null ga futsuu no kekka nara, sono imi wa true/false ya 0/1 no imi to onaji gurai, meiryuu de nakereba narimasen.
Kangae o kantan na rei de kakunin shimashou. Kotlin no tutorial-teki na rei de wa parser ga yoku demasu: moji ga suuji de nakereba null o kaesu. Kore wa totemo seijitsu na contract desu: “parse dekinakatta—sono signal da, exception mo fushigi mo nashi”.
fun parsePort(raw: String): Int? {
val trimmed = raw.trim()
return trimmed.toIntOrNull()
}
fun main() {
println(parsePort("8080")) // 8080
println(parsePort("oops")) // null
}
Koko de no null wa guutai-teki na imi o mochimasu: “moji-retsu ni seikaku na seisu ga fukumarena i”. Kore wa system error demo bug demo “nandaka okashii” demo naku, input no sakai de okiru futsuu no jyoutai desu.
De wa, tsugi no you ni shita to shimasu:
fun loadConfigText(): String? {
// ... read something
return null
}
Soshite owari. Kono null wa nani o imi shimasu ka? config ga mitsukaranai? kengen ga nai? file ga karappo? function o kakikake? Kore wa warui contract desu: caller ni suiri/atari o semarimasu.
Kagi ni naru kijun: ? o tsukeru nara, “naze value ga nai koto ga arieru no ka?” ni tsuite, “douryoukusurunoga mendou dakara” mitai ni mienai you ni kotaeru gimu ga arimasu.
2. null ga futsuu ni yurusareru basho: program no kyokai
Taitei null wa system no sakai de sugureta tool desu. Yosoku funou na sekai to mukiau basho—user input, command-line arguments, network data, file read, key search (element ga jissai ni sonzai shinai koto ga arieru) nado. Sakai de wa sekai ga “mu”, hen na moji, “nanimo iretenai” o hakobu kenri ga arimasu. Soshite sono basho de wa null ga tekisetsu desu.
Kotlin de wa collection no kihon operation mo sono shisei o shimeshimasu: tatoeba Map de key de yomu to V? o kaeshimasu. Key ga sonzai shinai koto ga arieru shi, sore wa futsuu no scenario dakara desu. Kono basho de no null wa “mitsukaranai” to yomenai no de, “kowareta” de wa arimasen.
Watashitachi no jissen-teki na console app (kari ni ExpenseTracker to yobimashou: CLI de chiisai shishutsu kanri) ni chikai rei o mimashou. Tatoeba shishutsu list ga ari, id de shishutsu o sagashimasu. Expense? o kaesu no wa goku shizen desu: shishutsu ga sakujo sareta kamo shirenai, id ga machigatteiru kamo shirenai, user ga machigaeta kamo shirenai.
data class Expense(
val id: Int,
val title: String,
val amount: Int
)
fun findExpenseById(expenses: List<Expense>, id: Int): Expense? {
return expenses.find { it.id == id }
}
fun main() {
val expenses = listOf(
Expense(id = 1, title = "Coffee", amount = 300),
Expense(id = 2, title = "Book", amount = 1200),
)
val e = findExpenseById(expenses, 2)
println(e?.title) // Book
}
Chuumoku shite kudasai: contract ga kanpeki ni yomemasu. Koko no Expense? wa “mitsukaranai kamoshirenai” o imi shimasu. Soshite kore wa “error” de wa naku, domain no ichi bu desu.
3. null ga jama ni naru basho: model ya business logic no naka
Program no naka (data ga ninshiki sare, kensa zumi no ato) de wa null ga yoku “chaos no usumaku” ni kawarimasu. Riyuu wa tanjun de, null ga code layer o shimi dasu kara desu. Hitotsu no nullable field ga futatsu-me o tsurete, tsugi ni mittsu-me… soshite formatting ni ?., keisan ni ?:, 3-kasho de if (x != null)… saigo ni wa “sorette, dou iu object ga ‘seijou’ na no?” to iu tetsugaku mondai ni narimasu.
Warui version no shishutsu model o kangaete mimashou:
data class ExpenseDraft(
val title: String?,
val amount: Int?
)
fun main() {
val draft = ExpenseDraft(title = null, amount = null)
println("title=${draft.title}, amount=${draft.amount}") // title=null, amount=null
}
Soto kara miru to benri sou desu: “nanika demo tsukureru”. Demo tsugi ni yaritai koto wa:
- user ni shishutsu o hyouji suru,
- goukei o keisan suru,
- sort suru,
- grouping suru.
Soshite dono basho demo “koko de null ni naru?” to kangaeru koto ni narimasu. Kore wa “ichio” to iu riyuu de, ie no daidokoro de kasa o motsu you na mono: dekiru kedo, ryouri ga yori fuben ni narimasu.
Kyou no lecture no juuyou point: “futsuu” no model no naka de nullable field ga aru to, data no stage ga mazatteiru koto ga ooi. “nama no input” ga ari, “valid na entity” ga arimasu. Onaji type ni mazete shimaeba, null wa sugu ni hirogarimasu.
4. null no futatsu no imi: “data ga nai” to “error”
Kono bubun wa tokuni juuyou desu. Koko kara saiai no bug ga hajimarimasu—sugu ni crash suru mono de wa naku, shizuka ni logic o kowasu mono desu.
null wa taitei futatsu no chigau situation de tsukawaremasu:
| Situation | Imi toshite nani ga okiteiru ka | null o kaesu no wa OK? | Example |
|---|---|---|---|
| Value ga sonzai shinai | Value wa sonzai shinai koto ga arieru, soshite sore wa kitai sareteiru | Hai | “id de mitsukaranai”, “empty input”, “suuji ga parse dekinai” |
| Error / fukanou | Value ga hoshikatta ga, mondai ga atte torenakatta | Kiken | “file ga yomenakatta”, “network error”, “logic ga kowareta” |
Mondai wa, donora mo gijutsu-teki ni wa onaji sugata ni naru koto desu: “null o kaeshita”. Demo imi wa “pan ga nai” to “mise ga yaketa” gurai chigaimasu.
Warui rei o wazato tsukutte, naze warui ka o mimashou:
fun loadUserName(userId: Int): String? {
// Suppose there could be a database error here,
// but we just returned null
return null
}
Caller no code wa mou kubetsu dekimasen:
- sono id no user ga jissai ni inai (normal),
- user wa iru ga DB ga down shita (normal ja nai),
- developer ga function o mada implement shiteinai (kore mo normal ja nai).
Soshite tsugi no you na code ga yoku kakaremasu:
val name = loadUserName(10) ?: "UNKNOWN"
println("Hello, $name") // Hello, UNKNOWN
Koko de “silent bug” ga okimasu: program wa ugokitsudzukeru ga, data no imi ga kowareteiru. Crash yori kiken desu. Crash nara “tashika ni okashii” to sakebimasu ga, "UNKNOWN" wa report ni mo export ni mo, goukei ni mo, sono mama nagarete shimaimasu.
Kyou no mokuhyou wa, kono you na basho o miwakere,null o bannou no “tsumekomi” toshite tsukawanai koto desu.
5. Practice: null o seigyo suru houhou
Kijun: “null o ichibun de setsumei dekiru ka?”
Design o tetsugaku ni shinai tame ni, totemo jitsumu-teki na test ga yakudachimasu.
Function/field ga T? no type nara, sore ni tsudzuku 1-gyou comment o, hazukashigaranai de kakete miru to ii deshou. Danraku de wa naku, “eto, maa…” demo naku, hitokoto desu.
Tatoeba yoi variant:
- findExpenseById(...) : Expense? — “expense o kaesu. mitsukaranakereba null”.
- parseAmount(...) : Int? — “kingaku o kaesu. moji ga seisu de nakereba null”.
- normalizeTitle(...) : String? — “space o nozoku. trim go ni empty nara null”.
Gyakuni, tsugi no you na warui variant wa keikai subeki desu:
- “nanika umaku ikanai toki wa null”
- “error no baai wa null”
- “null o kaesu kamoshirenai, yoku wakaranai”
Kono you na iikata ni natteiru nara, taitei null ni “error ya betsu no state” o kakushiyou to shiteiru kanousei ga takai desu.
ExpenseTracker: contract o yomiyasuku suru
Ima wa “koudo” na kouzou ya atarashii result type (sore wa tsugi no lecture no tema) o tsuika shimasen. Kawari ni, T ka T? ka o tadashiku erabi, contract o meiryuu ni suru renshuu o shimasu.
User input no normalization: String? ga tekisetsu
User wa empty string, space dake no string, mata wa “Enter dake oshite nanimo iwanai” kamoshirenai. Kore wa classic na boundary desu. Koko de no null wa seijitsu desu.
fun normalizeNonEmptyText(raw: String): String? {
val s = raw.trim()
return if (s.isEmpty()) null else s
}
fun main() {
println(normalizeNonEmptyText(" hello ")) // hello
println(normalizeNonEmptyText(" ")) // null
}
Koko no null wa “normalize shita kekka, text ga nai” o imi shimasu. Kore wa data no sonzai shina i koto de, error de wa arimasen.
Number parsing: Int? ga tekisetsu
Kotlin wa kono style ni shizen ni michibikimasu: toIntOrNull() wa parse dekinai koto ga aru kara nullable o kaeshimasu. Kore wa “kitai sareta shippai” no rei de, yoi pattern desu.
fun parseAmount(raw: String): Int? {
val s = raw.trim()
return s.toIntOrNull()
}
fun main() {
println(parseAmount("1200")) // 1200
println(parseAmount("12o0")) // null
}
Collection search: Expense? ga tekisetsu
“mitsukaranai”. Futsuu no hanashi desu.
fun removeExpenseById(expenses: MutableList<Expense>, id: Int): Boolean {
val found = expenses.find { it.id == id } ?: return false
expenses.remove(found)
return true
}
fun main() {
val expenses = mutableListOf(
Expense(1, "Coffee", 300),
Expense(2, "Book", 1200),
)
println(removeExpenseById(expenses, 2)) // true
println(removeExpenseById(expenses, 99)) // false
}
Koko de wa, Expense? o soto ni nagasanai you ni, wazato shiteimasu. “delete” function wa nai bu de nullable search o tsukau ga, soto ni kaesu no wa tanjun de meiryuu na kekka: Boolean (“delete shita / shinai”). Kore mo bunka desu: nullable wa, dete kita basho no chikaku ni tome, dekiru nara soto ni wa tsukai yasui contract o kaesu.
Antipattern: compiler ga urusai kara “zenbu nullable”
Totemo yuuwaku ga arimasu: compiler ga “nullable ni access shiteiru” to shikar u—suru to “jaa zenbu nullable ni shite, sekai moete shim ae” to naru. Mijikai kikan de wa raku ni natt a you ni mieru ga, nagai me de wa code ga “?. o tsukewasureta basho sagashi” quest ni narimasu.
Chigai o kanjiru tame ni, tsugi no formatting no 2-tsu no approach o hikaku shite kudasai:
fun formatExpenseBad(title: String?, amount: Int?): String {
val safeTitle = title ?: "UNKNOWN"
val safeAmount = amount ?: 0
return "$safeTitle: $safeAmount"
}
fun main() {
println(formatExpenseBad(null, null)) // UNKNOWN: 0
}
Ikken, program wa crash shimasen. Demo data wa mou sashi kaete imasu. 0 wa “amount ga nai” de wa naku “amount ga zero” desu. Sore de report ga uso ni naru kamoshirenai.
Moshi anata no app de 0 ga yurusareru shishutsu (tatoeba promo code, waribiki, henkin) nara, mou “empty” to “zero” o kubetsu dekimasen. Kore ga, null ga imi no contract de ari, “tada no value ga nai” de wa nai riyuu no rei desu.
Sentinel values de null o kawari ni suru: naze kiken ka
Tokidoki developer wa “null ga kirai, dakara kawari ni -1 o tsukao u” to iimasu. Kono you na tokubetsu no suu ji/moji wa sentinel to yobare, “nani mo nai” o imi shimasu.
Kore ga umaku iku koto mo arimasu ga, risk ga arimasu: code ni kakureta goi (yakusoku) o tsuika shite shimau koto desu. Hitotsu demo -1 check o wasureru to logic ga kowareru no ni, compiler wa tasuke te kuremasen. Type wa mada Int no mama dakara desu.
Chiisai rei de, “ichio soreppoi” ga imi wa mou machigatte iru, to iu pattern o mimashou:
fun parseAmountOrMinusOne(raw: String): Int {
return raw.trim().toIntOrNull() ?: -1
}
fun main() {
val amount = parseAmountOrMinusOne("oops")
println(amount + 100) // 99 (and this looks as if everything is fine)
}
Dakara Kotlin wa nullable o susumemasu: Int? nara “value ga nai” case o akiraka ni handling suru hitsuyou ga ari, -1 nara “tama tama wasureru” ga okiruyasui.
Kore wa “sentinel wa kanarazu warui” to iu imi de wa arimasen. Tada, tsukau nara sore o contract ni shinakereba naranai—“shizuka na urawaza” ni shite wa ikemasen.
“shori no gate” o hitotsu ni: null o hiroge nai
Yoi code de wa yoku, null ga hitotsu no basho ni suma i tsuiteiru style ga mimasu: input ya search no chikaku de, soko kara saki wa guutai-teki na action ni kawaru ka, soko de kirisuterareru. Warui code de wa null ga subete no layer ni shimidasu: domain model, report, formatting, sorting.
Gairon toshite wa tsugi no you ni narimasu:
flowchart LR
A["External world (input, search, data)"] -->|may be null| B["Gate: normalization/validation"]
B -->|non-null| C["Internal logic (model, calculations)"]
B -->|no value| D["Clear reaction (message/branch/exit)"]
Tsumari, code no naka de mainichi “null dattara dou suru?” o kurikaesanai you ni suru, to iu idea desu. Hitotsu no wakariyasui basho de kettei shi, soko ni matomeru.
Tatoeba command parsing de wa:
data class AddExpenseCommand(val title: String, val amount: Int)
fun parseAddCommand(line: String): AddExpenseCommand? {
val parts = line.trim().split(" ")
if (parts.size < 3) return null
val title = parts[1].trim().ifEmpty { return null }
val amount = parts[2].trim().toIntOrNull() ?: return null
return AddExpenseCommand(title = title, amount = amount)
}
fun main() {
println(parseAddCommand("add coffee 300")) // AddExpenseCommand(title=coffee, amount=300)
println(parseAddCommand("add coffee oops")) // null
}
Koko de null wa guutai-teki ni “command ga fuseikaku” o imi shimasu. Soshite juuyou na no wa, null ga kore ijou saki ni shimidasanai koto desu. AddExpenseCommand(title: String?, amount: Int?) no you ni wa shimasen. Seijou na command o kaesu ka, “ninshiki dekinakatta” signal toshite null o kaesu ka, desu.
Extension function de nullable receiver: check o kyokuchika suru
Tokidoki, value ga null demo ugoku chiisana utility o tsukuritai koto ga arimasu. Kotlin de wa nullable type (Any?, String? nado) ni taisuru extension function o kakemasu. Kore wa, onaji check o hitotsu no basho ni kakushite, call site de mainichi kakana i you ni suru no ni yuu kou desu. Kotlin no official docs demo, Any? no extension ga crash shinai you ni "null" string o kaesu rei ga arimasu. Body no naka de this == null o check shita ato wa, compiler ga this ga non-null da to rikai shimasu.
Watashitachi no app nara, motto shimple na mono—anzen na text hyouji—o tsukuremasu:
fun String?.toUiText(): String {
return this?.trim()?.takeIf { it.isNotEmpty() } ?: "<empty>"
}
fun main() {
val a: String? = " hello "
val b: String? = " "
val c: String? = null
println(a.toUiText()) // hello
println(b.toUiText()) // <empty>
println(c.toUiText()) // <empty>
}
Bimyouna point: kore wa UI/output ni wa tekisetsu desu ga, keisan ya data storage de wa itsumo tekisetsu to wa kagirimasen. Model no naka de "<empty>" wa hen na “sentinel” ni nari, console print ni wa meiryuu na sentaku toshite arieru, to iu koto desu.
6. null ni kansuru yoku aru miss
Miss 1: model field o “念のため” nullable ni suru.
Ooku wa “toriaezu object o tsukuri tai” to iu yokkyuu kara okimasu. Kekka, object wa tsukuri yasui ga tsukai nikui: doko demo ?. o wasurenai you ni shi, “nai baai dou suru?” o kangaeru hitsuyou ga arimasu. Taitei, “nama input” to “valid entity” o onaji type ni mazeta sign desu.
Miss 2: “mitsukaranai” mo “error” mo onaji null de kaesu.
Kono contract wa caller ni riyuu o suiri sasenakereba naranai. Soreyue, ?: de “damatte naosu”, !! de crash suru, mata wa "UNKNOWN" o dashite data o kowasu—no izureka ni narigachi desu. “nanika okashii toki wa null” to iikaketa nara, contract ga kasundeiru signal desu.
Miss 3: null-contract no design o !! operator de goka mas u.
!! ga hitsuyou na toki mo arimasu ga, jissen de wa “mou kangaeru no tsukareta” ni narigachi desu. Mondai wa imi no mondai ga kaiket sarenai koto: tada crash o runtime ni oshi tsuke ta dake desu. “nullable wa value ga nai kamoshirenai” to itte iru noni, “aru tei de tsukau” to iu koto ni narimasu.
Miss 4: gouri-teki na policy nashi ni null o sentinel (0, -1, "UNKNOWN") de okikae ru.
Default value o irete shimau to, data no imi ga kawarimasu. Tokidoki (tokuni UI) de wa yoi ga, policy ga naku domain rikai mo naku okonau to, shizuka na logic error ni narimasu: goukei ga “nanka awanai”, report ga “nanka soreppoi”, soshite user ga “nande "UNKNOWN: 0" nano?” to tou.
Miss 5: hitotsu no gate de shori suru kawari ni, pipeline juu ni null o hirogeru.
null ga 5–10 no function o tooru to, doko de deta no ka, nani o imi suru no ka o kanri dekinaku narimasu. Yori tsuyoi no wa, null ga source (input/search) no soba ni ite, sugu ni meiryuu na kettei ni naru koto: “mou ichido kike”, “mitsukaranai”, “command ga fuseikaku”.
GO TO FULL VERSION