第二张println错误:
智能转换为'布尔'是不可能的,因为'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
}
如果它为null,它会像第一个println一样打印null,为什么我必须这样做?
修改2
感谢您的所有答案,我现在明白了: 首先是println
println(message: Any?)
第二张println
println(message: Boolean)
因为r.isSquare = true使编译器信任isSquare是布尔值而不再是布尔值?
EDIT2
以下是我如何处理编译器以保持信任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
}
答案 0 :(得分:4)
由于r.isSquare
是一个可变属性,因此编译器无法在空检查后将其强制转换为非null属性。
您可以使用let
:
r.isSquare.let { println(it) }
let
只读取r.isSquare
的值一次,它在lambda中提供与it
相同的值。因此,即使在空检查之后,您也不必使用?
或!!
来访问布尔值。
来自Kotlin spec:
该语言使用有关前面检查的信息进行null检查 对于类型(是,!是),安全呼叫操作员(?。)和Nothing-returns 表达式,用于推断有关变量类型的其他信息 (除了从初始化者明确指定或推断的那个) 他们的声明)可能在某些块或更具体 甚至表达。然后使用此信息来启用更广泛的信息 对这些表达式进行操作并选择更具体的重载。
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
并将Any?
作为参数。
答案 1 :(得分:0)
为了使它工作,你必须在你的变量之后添加一个非null断言调用(!!)。无论是r !!。isSquare还是r.isSquare !!
fun main(args: Array<String>) {
val r: Rectangle = Rectangle(5,5)
println(r.isSquare)
r.isSquare = true println(r.!! isSquare)
}
data class Rectangle(var height: Int, var width: Int) {
var isSquare: Boolean? = null
}
答案 2 :(得分:0)
因为isSquare是一个可变属性(var)。它意味着你在哪里写一个值,然后你读它,另一个线程可以修改它,并因此得到一个NPE。
r.isSquare = true
//Another thread set r.isSquare = null
println(r.isSquare) // you get a null pointer exception
每次使用可空的变量时,您都必须检查属性的可空性。
答案 3 :(得分:0)
因为Android中的println()函数不支持布尔值?和布尔值? kotlin中的可变属性无法通过Kotlin的智能角色自动打开。
试用String?还是Int?或任何具有可变和可空属性的类型都会发生同样的事情。