Z3n*_*3nk 4 null boolean thread-safety optional kotlin
第二个 println 错误:
智能转换为 'Boolean' 是不可能的,因为 'r.isSquare' 是一个可变属性,此时可能已更改
fun main(args: Array<String>) {
val r: Rectangle = Rectangle(5,5)
println(r.isSquare)
r.isSquare = true
println(r.isSquare) // error but works with println(r.isSquare?:false)
}
data class Rectangle(var height: Int, var width: Int){
var isSquare: Boolean? = null
}
Run Code Online (Sandbox Code Playgroud)
如果它是空的,它会像第一个 println 一样打印空,为什么我必须这样做?
编辑 2
感谢您的所有回答,我现在明白:第一个 println 是
println(message: Any?)
Run Code Online (Sandbox Code Playgroud)
第二个 println 是
println(message: Boolean)
Run Code Online (Sandbox Code Playgroud)
因为 r.isSquare = true 使编译器相信 isSquare 是布尔值而不是布尔值?
编辑2
这是我如何处理编译器以保持信任 isSquare 是布尔值?
fun main(args: Array<String>) {
val r: Rectangle = Rectangle(5, 5)
println(r.isSquare)
r.isSquare = true as Boolean? // if no cast, he will try wrong println signature
println(r.isSquare)
}
data class Rectangle(var height: Int, var width: Int){
var isSquare: Boolean? = null
}
Run Code Online (Sandbox Code Playgroud)
由于r.isSquare
是可变属性,编译器无法在空检查后将其智能转换为非空属性。
您可以使用let
:
r.isSquare.let { println(it) }
Run Code Online (Sandbox Code Playgroud)
let
只读取r.isSquare
一次的值,它提供与it
lambda 内部相同的值。因此,即使在空检查之后,您也不必使用?
或!!
访问布尔值。
来自Kotlin 规范:
该语言使用有关前面的 null 检查、类型检查 (is, !is)、安全调用运算符 (?.) 和 Nothing-returning 表达式的信息来推断有关变量类型的其他信息(除了显式指定或从初始化程序推断的)他们的声明)在某些块甚至表达式中可能更具体。然后使用此信息来启用对这些表达式的更广泛的操作集并选择更具体的重载。
Run Code Online (Sandbox Code Playgroud)fun main(args: Array<String>) { var x : Any x = "" x.toUpperCase() // OK, smart cast to String }
第一个println
使用这个println(message: Any?)
由于您正在分配true
给isSquare
下一个,当您尝试打印isSquare
该Boolean
类型时,编译器会尝试将其智能转换为该类型。但它不能智能转换,因为该属性是可变类型。
如果删除该行, r.isSquare = true
,则编译器不会尝试将其智能转换为Boolean
并使用println
withAny?
作为参数。
归档时间: |
|
查看次数: |
2300 次 |
最近记录: |