Intro
kotlin中判空可以使用"?"直接处理
// java
void test(String a) {
if (a != null) {
print(a);
}
}
// kotlin
fun test(a: String?) = a?.let {
println(a)
}
那么else的逻辑如何处理呢
这就要引入今天的主角 elvis表达式,即"?:"的用法
// java
void test(String a) {
if (a != null) {
print(a);
} else {
print("null");
}
}
// kotlin
fun test(a: String?) = a?.let {
println(a)
} ?: let {
print("null")
}
这时候编译器就会提醒你上述方法可以简化
变成下面这种形式
但是这个形式不规整,于是“聪明的同学”就会增加大括号
fun test3(a: String?) = a?.let {
println(a)
} ?: {
println("canput")
}
但是这2个逻辑真的等价吗
实际运行时我们会发现并不等价,因为在上述函数中,当传入null时 并不能打印canput
Derivation
那么问题出在哪里呢,为了探究这个问题我们请出看源码的神器 show kotlin bytecode
fun test(a: String?) = a?.let {
println(a)
} ?: println("canput")
fun test1(a: String?) = a?.let {
println(a)
} ?: let {
println("canput")
}
fun test2(a: String?) = a?.let {
println(a)
} ?: run {
println("canput")
}
fun test3(a: String?) = a?.let {
println(a)
} ?: {
println("canput")
}
public final void test(@Nullable String a) {
if (a != null) {
int var5 = 0;
System.out.println(a);
Unit var2 = Unit.INSTANCE;
} else {
String var3 = "canput";
System.out.println(var3);
}
}
public final void test1(@Nullable String a) {
if (a != null) {
int var5 = 0;
System.out.println(a);
Unit var2 = Unit.INSTANCE;
} else {
newtest it = this;
int var7 = 0;
String var6 = "canput";
System.out.println(var6);
}
}
public final void test2(@Nullable String a) {
if (a != null) {
int var5 = 0;
System.out.println(a);
Unit var2 = Unit.INSTANCE;
} else {
newtest $this$test2_u24lambda_u244 = this;
int var7 = 0;
String var6 = "canput";
System.out.println(var6);
}
}
@NotNull
public final Object test3(@Nullable String a) {
Object var10000;
if (a != null) {
int var5 = 0;
System.out.println(a);
Unit var2 = Unit.INSTANCE;
var10000 = var2;
} else {
var10000 = newtest::test3$lambda$6;
}
return var10000;
}
private static final Unit test3$lambda$6() {
String var0 = "canput";
System.out.println(var0);
return Unit.INSTANCE;
}
可以很明显看到前3个方法都可以执行,但是test3中的逻辑被封装成了一个静态方法作为返回值return 实际里面的逻辑不会执行
Conclusion
?: 等效于 else { }
如下所示 只有加上run/let等关键字 才可以执行里面的方法
fun test3(a: String?) = a?.let {
println(a)
} ?: {
println("canput")
}
fun test3(a: String?) {
if (a != null) {
println(a)
} else {
{
println("canput")
}
}
}