Kotlin občas na úrovni byte kódu generuje různý boilerplate, např. v podobě checků inicializace lateinit proměnných, a až donedávna mi unikala jednoduchá, avšak svým významem docela důležitá věc. Říkal jsem si, že pokud aplikace padne na NullPointerException v Javě, anebo na UninitializedPropertyAccessException v Kotlinu, tak že je to v důsledku totéž. Nicméně je zde jeden případ, kdy lateinit jednoznačně vede. Mějme tento kód v Javě:
package com.svetylkovo.kotlin.lateinit; public class WithoutLateinit { private static String first; private static String second; public static void main(String[] args) { first = "First!"; System.out.println("Total length is "+ String.valueOf(first.length() + second.length())); } }
Pokud tento kód spustíme, dostaneme:
Exception in thread "main" java.lang.NullPointerException
at com.svetylkovo.kotlin.lateinit.WithoutLateinit.main(WithoutLateinit.java:9)
Po nalezení řádku kódu, kde NullPointerException nastal, si můžeme jen lámat hlavu, která z těch dvou proměnných vlastně null byla a často (v reálných aplikacích) na to musíme ne-zcela triviálním způsobem přijít. Zkusme si stejnou situaci nasimulovat v Kotlinu s pomocí lateinit:
package com.svetylkovo.kotlin.lateinit object LateinitTest { lateinit var first: String lateinit var second: String @JvmStatic fun main(args: Array<String>) { first = "First!" println("Total length is ${first.length + second.length}") } }
Když spustíme tento kód, aplikace padne na:
Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property second has not been initialized
at com.svetylkovo.kotlin.lateinit.LateinitTest.main(LateinitTest.kt:10)
kde stacktrace mluví za vše a místo toho, abych teprve začal hledat, co se vlastně stalo špatně, okamžitě vím, že to byla proměnná second, kterou jsem z nějakého (v tomto případě záměrného) důvodu zapomněl inicializovat.
Posuďte sami, krom toho, že nás Kotlin dokáže NullPointerException zbavit již za překladu téměř úplně, nebylo by lepší v případech, kdy už by tato výjimka musela nastat, dostávat raději UninitializedPropertyAccessException s přesným popisem viníka, který za to může? 🙂