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? 🙂