Kotlin: deklarovat typ proměnných explicitně?
Poté, co jsem dopsal blog o dojmech z Kotlinu, napadla mě ex-post ještě jedna myšlenka k tématu, jestli uvádět typ proměnné explicitně nebo ne: jaký bude výsledný kód po kompilaci? Pojďme udělat experiment. Vezměme tentýž zdroják, jednou s automatickými typy proměnných, podruhé s explicitně uvedenými typy. Nechme ho zkompilovat a výsledek dekompilujme do Javy. Bude ve výsledku nějaký rozdíl?
Pro účely pokusu použijme již zmíněnou ukázku pro získání stručného výpisu příspěvku. Nejprve s automatickými typy proměnných:
fun parseSummary(src: String): String {
val doc = Jsoup.parseBodyFragment(src)
val body = doc.body()
val p = body.select("p").first()
var retval = p?.text() ?: Jsoup.clean(src, Whitelist.none())
if (retval.isNotEmpty()) {
retval = retval.trim()
}
return retval
}
A s explicitně uvedenými typy:
fun parseSummary2(src: String): String {
val doc: Document = Jsoup.parseBodyFragment(src)
val body: Element = doc.body()
val p: Element? = body.select("p").first()
var retval : String = p?.text() ?: Jsoup.clean(src, Whitelist.none())
if (retval.isNotEmpty()) {
retval = retval.trim()
}
return retval
}
Zdroják byl zkompilován přímo v Android Studiu, jako dekompilátor jsem použil CFR verzi 0.131.
Ještě pro úplnost, zdroják využívá knihovnu Jsoup pro zpracování HTML.
Hypotéza: zdroják s explicitně uvedenými typy bude zkompilován efektivněji, explicitně uvedené typy pomohou kompilátoru lépe s typy pracovat.
Výsledek? Nejprve s automatickými typy:
@NotNull
public static final String parseSummary(@NotNull String src) {
Object retval;
Intrinsics.checkParameterIsNotNull((Object)src, (String)"src");
Document doc = Jsoup.parseBodyFragment((String)src);
Element body = doc.body();
Element p = body.select("p").first();
Object object = p;
if (object == null || (object = object.text()) == null) {
object = Jsoup.clean((String)src, (Whitelist)Whitelist.none());
}
Object object2 = retval = object;
Intrinsics.checkExpressionValueIsNotNull((Object)object2, (String)"retval");
CharSequence charSequence = (CharSequence)object2;
if (charSequence.length() > 0) {
charSequence = retval;
retval = StringsKt.trim((CharSequence)charSequence).toString();
}
Object object3 = retval;
Intrinsics.checkExpressionValueIsNotNull((Object)object3, (String)"retval");
return object3;
}
A s explicitně uvedenými typy:
@NotNull
public static final String parseSummary2(@NotNull String src) {
Intrinsics.checkParameterIsNotNull((Object)src, (String)"src");
Document document = Jsoup.parseBodyFragment((String)src);
Intrinsics.checkExpressionValueIsNotNull((Object)document, (String)"Jsoup.parseBodyFragment(src)");
Document doc = document;
Element element = doc.body();
Intrinsics.checkExpressionValueIsNotNull((Object)element, (String)"doc.body()");
Element body = element;
Element p = body.select("p").first();
Object object = p;
if (object == null || (object = object.text()) == null) {
String string = Jsoup.clean((String)src, (Whitelist)Whitelist.none());
object = string;
Intrinsics.checkExpressionValueIsNotNull((Object)string, (String)"Jsoup.clean(src, Whitelist.none())");
}
Object retval = object;
CharSequence charSequence = (CharSequence)retval;
if (charSequence.length() > 0) {
CharSequence charSequence2 = charSequence = retval;
if (charSequence2 == null) {
throw new TypeCastException("null cannot be cast to non-null type kotlin.CharSequence");
}
retval = StringsKt.trim((CharSequence)charSequence2).toString();
}
return retval;
}
Podíváme-li se na výsledek, zjistíme, že zdroják s explicitně uvedenými typy obsahuje více defenzivních kontrol na null
a používá více pomocných proměnných. Vypadá tedy méně efektivně než s automatickými typy.
Experiment hypotézu nepotvrdil, naopak ji úspěšně vyvrátil. Zdá se tedy, že automatický typ proměnné usnadňuje nejen psaní, ale i kompilaci.
Tagy: Java, Programování, Kotlin