ProgrammingAndroid 開発者

Kotlinの遅延初期化プロパティ('lateinit var')はどのように機能し、nullableプロパティと何が違い、どのような状況で使用するべきですか?

Hintsage AIアシスタントで面接を突破

回答

質問の背景

Kotlinは型安全性を重視し、nullポインタの回避を目指していますが、依存性注入やAndroid Activityの使用時など、変数の遅延初期化が必要となる場合がよくあります。そのため、lateinit修飾子が追加されました。

問題

通常のプロパティは必ず初期化する必要があるか、nullableでなければならず、遅延ながら必ず初期化が保証される場合には不便です。nullable型を使用するとコードが複雑になり、追加のnullチェックが必要になります。

解決策

lateinitを使用すると、初期化されていないプロパティを作成できますが、それを最初に使用する前に初期化することをコンパイラに約束します。コンストラクタではなく、後で初期化することも可能です。

class UserViewModel { lateinit var repository: UserRepository fun onCreate() { repository = UserRepository() } fun getData() = repository.load() }

主な特徴:

  • nullを使用せず、初期化を遅延させることができる
  • 初期化されていないlateinitプロパティにアクセスした場合、UninitializedPropertyAccessExceptionをスローする
  • varのみ使用可能で、primitiveタイプ(Int、Doubleなど)には使用できない

トリック質問

valプロパティにlateinitを使用できますか?

いいえ。lateinitはvarでのみ機能します。valは一度即座に初期化されるか、ゲッターを介して初期化される必要があります。

lateinitはInt、Boolean、Doubleなどのprimitiveタイプで機能しますか?

いいえ。オブジェクト参照型でのみ機能します。primitiveにはnullable型を使用してください。

初期化前にlateinitプロパティにアクセスした場合はどうなりますか?

KotlinはUninitializedPropertyAccessExceptionをスローします:

lateinit var foo: String println(foo) // 例外

よくあるエラーとアンチパターン

  • lateinitプロパティの初期化を忘れた—アプリケーションがクラッシュします
  • isInitializedのチェックが必要な場合に使用する
  • primitiveタイプおよびvalに適用する

実生活の例

ネガティブケース

開発者がlateinit var item: Stringを宣言し、getItemメソッドを呼び出すまで初期化しなかった。結果:アプリケーションがクラッシュしました。

メリット:

  • 正しく初期化されている場合はnullableを排除します

デメリット:

  • ライフサイクルを混同し、ランタイム例外を引き起こすリスクがあります

ポジティブケース

Android Activity:lateinit var presenter、onCreateで初期化。すべてのライフサイクルメソッドでpresenterを使用することが安全です:nullabilityは必要ありません。

メリット:

  • 読みやすさが向上し、余分なチェックを避けます
  • 必要な初期化を保証します

デメリット:

  • 初期化の順序を明示的に監視する必要があります