在价值影响之后,智能转换为'布尔'是不可能的

时间:2017-08-23 09:46:31

标签: kotlin null boolean thread-safety optional

第二张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
}

4 个答案:

答案 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?或任何具有可变和可空属性的类型都会发生同样的事情。