I personaly like the when
syntax as it causes identation to be much clearer. However I am concerned about the 'penalties' that I might be introducing by doing this.
I'm not really an expert on bytecode, but I can see that for the same 'logic', the when clause takes more bytecode operations.
Simple file with 3 different Kotlin functions
package com.whatever
fun method1(): String {
return if (BuildConfig.DEBUG) "something" else "else"
}
fun method2(): String {
return if (BuildConfig.DEBUG) {
"something"
} else {
"else"
}
}
fun method3(): String {
return when (BuildConfig.DEBUG) {
true -> "something"
else -> "else"
}
}
Generated bytecode
// access flags 0x19
public final static method1()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 4 L0
GETSTATIC com/whatever/BuildConfig.DEBUG : Z
IFEQ L1
LDC "something"
GOTO L2
L1
LDC "else"
L2
ARETURN
L3
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static method2()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 8 L0
GETSTATIC com/whatever/BuildConfig.DEBUG : Z
IFEQ L1
L2
LINENUMBER 9 L2
LDC "something"
L3
GOTO L4
L1
LINENUMBER 11 L1
LDC "else"
L5
LINENUMBER 8 L5
L4
ARETURN
L6
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static method3()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 16 L0
GETSTATIC com/whatever/BuildConfig.DEBUG : Z
ISTORE 0
L1
LINENUMBER 17 L1
ILOAD 0
ICONST_1
IF_ICMPNE L2
L3
LDC "something"
GOTO L4
L2
LINENUMBER 18 L2
LDC "else"
L5
LINENUMBER 16 L5
L4
ARETURN
L6
MAXSTACK = 2
MAXLOCALS = 1
Can someone point out how significant this cost is? And wether we should try to stay away from this pattern for simple operations?
Thanks
Kotlin has the following conditionals: Use if to specify a block of code to be executed, if a specified condition is true. Use else to specify a block of code to be executed, if the same condition is false. Use else if to specify a new condition to test, if the first condition is false.
For example, fun main(args: Array<String>) { val n = -1 when (n) { 1, 2, 3 -> println("n is a positive integer less than 4.") 0 -> println("n is zero") -1, -2 -> println("n is a negative integer greater than 3.") } } When you run the program, the output will be: n is a negative integer greater than 3.
Kotlin does not provide any option to write a switch-case statement. However, Kotlin provides an option to implement when() which works exactly the same way switch works in other programming languages.
Kotlin does not provide an option to write a switch-case statement; however we can implement the switch-case functionality in Kotlin using the when() function which works exactly the same way switch works in other programming languages.
The only difference here is that in method3
the BuildConfig.DEBUG
value gets stored in a local variable first. When decompiling the bytecode to Java, you see the following:
@NotNull
public static final String method2() {
return BuildConfig.DEBUG?"something":"else";
}
@NotNull
public static final String method3() {
boolean var0 = BuildConfig.DEBUG;
return var0?"something":"else";
}
This is negligible.
If we expand the if/else
clauses, we can construct the following:
fun method4(a: Int): String {
if (a == 1) {
return "1"
} else if (a == 2) {
return "2"
} else if (a == 3) {
return "3"
} else {
return "4"
}
}
fun method5(a: Int): String {
when (a) {
1 -> return "1"
2 -> return "2"
3 -> return "3"
else -> return "4"
}
}
The decompiled bytecode for this is:
@NotNull
public static final String method4(int a) {
return a == 1?"1":(a == 2?"2":(a == 3?"3":"4"));
}
@NotNull
public static final String method5(int a) {
switch(a) {
case 1:
return "1";
case 2:
return "2";
case 3:
return "3";
default:
return "4";
}
}
Thus, a simple when
statement boils down to a switch
statement in Java. See 'Why switch is faster than if' for a comparison between these two.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With