在下面的代码中,我正在创建一个Java集合。稍后当我将其转换为 Scala 时,我可以将null
存储在 Int
中。但是如果我直接创建 scala 地图,我无法存储null
。为什么?
scala> import collection.JavaConverters._
import collection.JavaConverters._
scala> val mapJava:java.util.HashMap[String,java.lang.Integer] = new java.util.HashMap[String,java.lang.Integer]
mapJava: java.util.HashMap[String,Integer] = {}
scala> mapJava.put("key",null)
res2: Integer = null
scala> println(mapJava)
{key=null}
scala> val mapScala = mapJava.asScala
mapScala: scala.collection.mutable.Map[String,Integer] = Map(key -> null)
scala> val mapScalaI = mapScala.asInstanceOf[scala.collection.Map[String,Int]]
mapScalaI: scala.collection.Map[String,Int] = Map(key -> null) //storing null in Int
//but I cannot store null in Int in following code. why?
scala> val mapScalaI2 = Map[String,Int]("key"->null)
<console>:14: error: an expression of type Null is ineligible for implicit conversion
val mapScalaI2 = Map[String,Int]("key"->null)
^
...
scala> val mapScala = mapJava.asScala
mapScala: scala.collection.mutable.Map[String,Integer] = Map(key -> null)
scala> val mapScalaI = mapScala.asInstanceOf[scala.collection.Map[String,Int]]
mapScalaI: scala.collection.Map[String,Int] = Map(key -> null) //storing null in Int
...
从理论上讲,mapScala.asInstanceOf[scala.collection.Map[String,Int]]
应该失败,因为 Integer
类型参数与Int
类型参数不同。但是,它实际上并没有这样做,因为asInstanceOf
由于 Java 类型擦除而没有(或不能(检查Map[String, Int]
的类型参数。从scala.Any.asInstanceOf
:
请注意,运行时强制转换的成功是模 Scala 的擦除语义。因此,表达式
1.asInstanceOf[String]
将在运行时引发ClassCastException
,而表达式List(1).asInstanceOf[List[String]]
不会。在后一个示例中,由于类型参数作为编译的一部分被擦除,因此无法检查列表的内容是否属于请求的类型。
在 Java 中,null
可以是任何引用类型的值,例如 java.lang.Integer
.
在Scala中,null
是Null
类型,它是任何引用类型的子类型。 scala.Int
是基元类型,而不是引用类型。
类型 Null 的表达式不符合隐式转换的条件