聪明的演员是不可能的,因为…是一个可变的财产,可能已经改变了这个时间
我正在努力获得一个类,它结合了Kotlin
列表,集合和地图。 我希望编写isScalar
函数,如果对象只包含一个元素并写入,它应该返回true
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap import it.unimi.dsi.fastutil.objects.ReferenceArrayList import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet class Args { var list : ReferenceArrayList? = null var set : ReferenceOpenHashSet? = null var map : Reference2ReferenceOpenHashMap? = null fun isEmpty() : Boolean { return list === null && set === null && map === null } fun isScalar() : Boolean { if(list !== null && list.size == 1) { return true } } }
不幸的是,它给了我比较错误
list !== null && list.size == 1
话
Smart cast to 'ReferenceArrayList' is impossible, because 'list' is a mutable property that could have been changed by this time
据我所知,这与multithreading的假设有关。 在Java中,如果期望multithreading,我会让函数synchronized
。 另外,如果我不写线程安全的话,我完全可以忽视这个。
我应该如何写Kotlin?
我看到这个解决方案https://stackoverflow.com/a/44596284/258483,但它期望MT,我不想。 如何避免智能铸造,如果它不能做到这一点?
UPDATE
问题是如何以相同的“程序”forms来做到这一点。 如何不使用智能铸造?
更新2
总而言之,就我所了解,根本不可能/合理地将variables与Kotlin中的null
进行比较。 因为一旦你比较了它,下一次你应该用null
这样的操作隐式地再次将它与null
比较.?
你无法避免这一点。
如果你利用了null
不能等于1
(或其他任何东西)的事实,你可以使这个检查非常简洁:
fun isScalar() : Boolean = list?.size == 1
当一个对list.size
的null-safe调用返回null时,我们得到false
因为1 != null
。 否则,无论什么价值size
回报作出比较,那就像你所期望的那样。
通过使用空安全运算符( ?.
),您完全避免了一个聪明的演员。 Kotlin为我们提供了精明的代码,使代码更加清晰,这也是保护我们免受滥用的特性之一 。 Kotlin不会保护我们不受任何东西的限制(例如零分,例如你在评论中使用的例子)。 你的代码陷入了一个合理的情况下,聪明的铸造可能出错,所以Kotlin跳进来帮忙。
但是,如果你确定没有其他线程正在工作,那么是的,这个检查是“错误的”。 在这种情况下,你不需要警告。 通过kotlinlang.org上的这个线程判断 ,你不是唯一的!
您可以执行空检查,如果成功,则使用let
访问variables的只读副本:
fun isScalar() : Boolean { return list?.let { it.size == 1 } ?: false }
- 如果
list
为null,则整个let
expression式将计算为null
,并且将返回Elvis运算符(false
)的右侧。 - 如果
list
不为null,则调用let
函数,并返回it.size == 1
expression式的结果 –it
指的是调用的对象(本例中为list
)。 由于它使用了一个安全的调用 ,it
它将有一个不可为空的types,并且可以调用它的size
。