两个函数test1和test2,一个用"is"检查类型,一个使用"as?
使用"Is"one_answers"as?"有比较吗?对这两个词的一般用法有什么建议?
class Message(val int: Int, val msg:String)
class Test {
fun test1(objList: List<Any?>) {
for (i in objList.size - 1 downTo 0) {
val item = objList.get(i)
if (item is Message) {
println(item)
}
}
}
fun test2(objList: List<Any?>) {
for (i in objList.size - 1 downTo 0) {
(objList.get(i) as? Message)?.let {item ->
println(item)
}
}
}
}
因此,如果您查看两者的JVM字节码:
// JVM bytecode of test1
L5
LINENUMBER 8 L5
ALOAD 3
INSTANCEOF com/example/artifact/Message
IFEQ L6
// JVM bytecode of test2
L4
LINENUMBER 16 L4
ALOAD 0
ILOAD 1
INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object; (itf)
DUP
INSTANCEOF com/example/artifact/Message
IFNE L5
POP
ACONST_NULL
L5
CHECKCAST com/example/artifact/Message
DUP
IFNULL L6
ASTORE 3
您可以清楚地看到,test1
只检查类型,它智能地强制转换结果,而test2
首先检查实例是否属于该类型,然后返回null或显式地将其"强制转换"为该类型。
因此,通过观察,我建议您使用is
运算符,因为它对这些任务进行了更优化。如果你不喜欢使用大括号,那么你可以像python一样省略它们,或者把println放在与If条件相同的行上。
如果你想的话,这是一个更优化的代码:
fun test1(objList: List<Any>) {
for (item in objList.asReversed()) {
if (item is Message) println(item)
}
}
fun test2(objList: List<Any>) {
for (item in objList.asReversed()) {
(item as? Message)?.let { println(it) }
}
}
as?
版本可能少了一行代码,但它真的整体代码少了吗?你可能已经摆脱了:
val item = objList.get(i)
但你用代替了它
(objList.get(i) as? Message)?.let {item ->
在这种情况下,我认为as?
版本比is
版本需要更多的时间来理解,后者更简单。我还怀疑这两种方法在性能上是否存在显著差异。一般来说,除非您已经分析了应用程序中的实际性能问题,否则总是更喜欢可读性更强的代码而不是性能更高的代码。是否存在性能问题在很大程度上取决于应用程序的上下文。记住,过早的优化是万恶之源。
如果你真的想要更少的代码,那么考虑使用以下代码:
fun test(objList: List<Any>) = objList.asReversed().forEach {
if (it is Message) println(it)
}
这利用了:
- 单表达式函数
List.asReversed
(返回原始列表的反向视图(Iterable.forEach
it
:单个参数的隐式名称(在lambda表达式中(
is
是类型检查。as
型铸造。
不同的是
is
返回布尔值、真或假
as
返回该类型
如果您只想得到"是"或"否",请使用is
示例
if (user is Login)
你只是想要答案是还是不是?然后你做其他事情
当您想尝试转换为该类型的时,可以使用as
示例
(user as? Admin).let{print(it.name.toString())}
您要检查的这个用户是否为is Admin or not
如果是,您想使用该用户值来打印类似名称的内容
所以对于条件使用is
铸造用as
fun test(objList: List<Any>) = objList.asReversed().forEach {
when(it){ is Message -> println(it)}
}