Kotlin 在简单条件下使用 when
Kotlin using when for simple conditions
我个人喜欢 when
语法,因为它使标识更加清晰。但是我担心这样做可能会引入 'penalties'。
我不是真正的字节码专家,但我可以看到对于相同的 'logic',when 子句需要更多的字节码操作。
具有 3 个不同 Kotlin 函数的简单文件
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"
}
}
生成的字节码
// 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
有人能指出这笔费用有多大吗?我们是否应该为了简单的操作而尽量远离这种模式?
谢谢
这里唯一的区别是在 method3
中,BuildConfig.DEBUG
值首先存储在局部变量中。将字节码反编译为 Java 时,您会看到以下内容:
@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";
}
这个可以忽略不计。
如果我们扩展if/else
子句,我们可以构造如下:
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"
}
}
反编译字节码为:
@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";
}
}
因此,一个简单的 when
语句归结为 Java 中的 switch
语句。请参阅 'Why switch is faster than if' 了解这两者之间的比较。
我个人喜欢 when
语法,因为它使标识更加清晰。但是我担心这样做可能会引入 'penalties'。
我不是真正的字节码专家,但我可以看到对于相同的 'logic',when 子句需要更多的字节码操作。
具有 3 个不同 Kotlin 函数的简单文件
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"
}
}
生成的字节码
// 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
有人能指出这笔费用有多大吗?我们是否应该为了简单的操作而尽量远离这种模式?
谢谢
这里唯一的区别是在 method3
中,BuildConfig.DEBUG
值首先存储在局部变量中。将字节码反编译为 Java 时,您会看到以下内容:
@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";
}
这个可以忽略不计。
如果我们扩展if/else
子句,我们可以构造如下:
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"
}
}
反编译字节码为:
@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";
}
}
因此,一个简单的 when
语句归结为 Java 中的 switch
语句。请参阅 'Why switch is faster than if' 了解这两者之间的比较。