lateinitと遅延初期化
後から代入するプロパティにはlateinitを、遅延計算にはby lazyを使用します。
「lateinitと遅延初期化」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。
遅延初期化のための2つの方法
コンストラクターの実行時にプロパティを初期化できない場合があります。Kotlin には、後から代入するvar向けのlateinitと、最初のアクセス時に計算するval向けのby lazyが用意されています。
lateinit の基本
lateinit varを使うと初期化を遅らせることができます。変数は null 非許容かつプリミティブ型ではないvarでなければなりません。代入前にアクセスするとUninitializedPropertyAccessExceptionがスローされます。
class Service {
lateinit var name: String
fun init(value: String) { name = value }
}
fun main() {
val s = Service()
s.init("MyService")
println(s.name)
}lateinit を使う理由
初期化がコンストラクターの外部で行われる依存性注入、テストフィクスチャ、またはフレームワークが管理するライフサイクル(Android のビューや Spring の Bean など)にはlateinitを使用します。
class Repository {
lateinit var db: String // assigned later by DI framework
fun query() = "querying $db"
}
fun main() {
val r = Repository()
r.db = "postgres://localhost"
println(r.query())
}isInitialized による確認
::propName.isInitializedを使うと、lateinitプロパティに値が代入済みかどうかを確認できます。
class Foo {
lateinit var bar: String
fun status() = if (::bar.isInitialized) "set to $bar" else "unset"
}
fun main() {
val f = Foo()
println(f.status()) // unset
f.bar = "hi"
println(f.status())
}lateinit の制限
プリミティブ型(Int、Boolean など)、null 許容型、またはvalにはlateinitを使用できません。これらの規則はコンパイラーによって強制されます。
// VALID:
lateinit var name: String
// INVALID:
// lateinit var count: Int // primitives not allowed
// lateinit val constant: String // val not allowed
// lateinit var maybe: String? // nullable not allowed
fun main() { name = "ok"; println(name) }by lazy の基本
by lazyを使うと、valの初期化を最初のアクセスまで遅らせることができます。ラムダは1回だけ実行され、結果がキャッシュされます。
val expensive: String by lazy {
println("Computing...")
"result"
}
fun main() {
println(expensive) // Computing... then result
println(expensive) // result (cached)
}by lazy を使う理由
初期化にコストがかかり、必要にならない可能性がある場合(後で使うためにキャッシュする場合)や、初期化がすでに構築済みの他のプロパティに依存する場合はby lazyを使用します。
class Config {
val parsed: Map<String, String> by lazy {
println("parsing config...")
mapOf("host" to "localhost", "port" to "8080")
}
}
fun main() {
val c = Config()
println("config object created — not parsed yet")
println(c.parsed["host"]) // now parses
println(c.parsed["port"]) // cached
}lazy のスレッドセーフ性モード
デフォルトでは、by lazyはLazyThreadSafetyMode.SYNCHRONIZEDを使用します。並行実行しても問題ない初期化にはPUBLICATIONを、シングルスレッドでの性能を優先する場合はNONEを使用します。
val safe: String by lazy { "thread-safe" }
val fast: String by lazy(LazyThreadSafetyMode.NONE) { "fast, single-thread" }
fun main() {
println(safe)
println(fast)
}lateinit と lazy の比較
lateinit:varで、外部から代入します。by lazy:valで、最初のアクセス時にプロパティ自身が計算します。
class Demo {
lateinit var injected: String // assigned by caller
val computed: String by lazy { "computed once" }
}
fun main() {
val d = Demo()
d.injected = "from outside"
println(d.injected)
println(d.computed)
}他のプロパティを読み取る lazy
lazy プロパティは、先に初期化された他のプロパティを読み取り、それらを組み合わせることができます。
class User(val first: String, val last: String) {
val fullName: String by lazy { "$first $last" }
}
fun main() {
val u = User("Ada", "Lovelace")
println(u.fullName)
}実践的なパターン
同じクラス内で、DI にはlateinitを、派生状態にはby lazyを組み合わせます。
class App {
lateinit var config: Map<String, String>
val host: String by lazy { config["host"] ?: "localhost" }
}
fun main() {
val app = App()
app.config = mapOf("host" to "api.example.com")
println(app.host) // api.example.com
}クイックチェック
valプロパティの初期化を最初のアクセスまで遅らせるキーワードはどれですか?
まとめ
フレームワークや DI によって後から代入される null 非許容の可変プロパティには、lateinit varを使用します。最初のアクセス時に1回だけ計算する読み取り専用の値には、val by lazyを使用します。状態は::prop.isInitializedで確認できます。
AI チューターと学ぶ Kotlin — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 51
- レッスン
- 203
よくある質問
「lateinitと遅延初期化」レッスンは無料ですか?
はい。「lateinitと遅延初期化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。
「lateinitと遅延初期化」で何を学びますか?
後から代入するプロパティにはlateinitを、遅延計算にはby lazyを使用します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Kotlin Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「lateinitと遅延初期化」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このKotlin Academyレッスンでコードを書いて実行できますか?
はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。