短路逻辑或/与

Posted on By ᵇᵒ

今天写了如下一段 kotlin 代码:

fun foo(uid: Int, list: List<Int>): Boolean  = 
    list.isEmpty() or ((list.size == 1) and (list[0] == uid))

这段代码意图传入一个用户 id 列表和一个指定用户 id,如果列表为空、或者列表只包含指定的用户 id,返回 true,否则返回 false。

很简单的一段代码,部分场景崩了。原因是列表为空时,中缀操作符 or 后面的表达式会继续执行,导致数组越界异常。

想当然地以为 or 和 and 是短路逻辑,看了下源码才发现这两并不是短路的。反编译其对应的 java 字节码,底层实现使用的是非短路逻辑运算符 | &

public final boolean foo(int uid, @NotNull List list) {
    Intrinsics.checkNotNullParameter(list, "list");
    return list.isEmpty() | list.size() == 1 & ((Number)list.get(0)).intValue() == uid;
}

解决方式很简单,将中缀操作符 or and 换成短路逻辑运算符 || && 即可:

fun foo(uid: Int, list: List<Int>): Boolean =
    list.isEmpty() || (list.size == 1 && list[0] == uid)