scala mutable.Map put/get句柄为null';是以一种意想不到的方式吗?
我知道scala中不应该使用空值,但有时在与Java进行互操作时会出现这种情况。scala可变映射处理此问题的方式似乎不太合适:scala mutable.Map put/get句柄为null';是以一种意想不到的方式吗?,scala,Scala,我知道scala中不应该使用空值,但有时在与Java进行互操作时会出现这种情况。scala可变映射处理此问题的方式似乎不太合适: scala> import scala.collection.mutable import scala.collection.mutable scala> val m: mutable.Map[String, String] = mutable.Map.empty m: scala.collection.mutable.Map[String,String
scala> import scala.collection.mutable
import scala.collection.mutable
scala> val m: mutable.Map[String, String] = mutable.Map.empty
m: scala.collection.mutable.Map[String,String] = Map()
scala> m.put("Bogus", null)
res0: Option[String] = None
scala> m.get("Bogus")
res1: Option[String] = Some(null)
scala> m.getOrElse("Bogus", "default")
res2: String = null
在这种情况下,我希望m.get
返回None
。几乎像是一个bug,就像在代码的某个地方有一个Some(v)
而不是选项(v)
是否有关于更改此行为的讨论?
Null
是String
的子类型:
scala> implicitly[Null <:< String]
res3: Null <:< String = <function1>
如果您想在映射中将null
存储为String
,这是您的权利
与Java的
Map#get
(我们称之为javaLikeGet
)相比,Scala的get
的行为大致如下:
def get(k: K) = if (containsKey(k)) {
Some(this.javaLikeGet(k))
} else {
None
}
和你想象的不一样:
def get(k: K) = Option(this.javaLikeGet(k))
后一个版本(可能是您认为的)将为现有密钥获取null
,将其传递到选项(…)
,然后返回None
。但是前一个版本(模拟实际实现的工作方式)会注意到键的存在,并将javaLikeGet
返回的null
包装成Some
简单而一致的规则是:
如果键k
存在,则get(k)
返回Some[V]
,否则返回None
这比Java的get
在两种完全不同的情况下返回null
的奇怪行为要少得多
这是一个耗资数十亿美元的错误,但Scala不太可能修复它,因为它必须与Java进行互操作。我的猜测是,现在和将来都不会讨论改变这种行为,至少在整个编程环境发生根本性变化之前是这样。
Null
是String
的子类型:
scala> implicitly[Null <:< String]
res3: Null <:< String = <function1>
如果您想在映射中将null
存储为String
,这是您的权利
与Java的
Map#get
(我们称之为javaLikeGet
)相比,Scala的get
的行为大致如下:
def get(k: K) = if (containsKey(k)) {
Some(this.javaLikeGet(k))
} else {
None
}
和你想象的不一样:
def get(k: K) = Option(this.javaLikeGet(k))
后一个版本(可能是您认为的)将为现有密钥获取null
,将其传递到选项(…)
,然后返回None
。但是前一个版本(模拟实际实现的工作方式)会注意到键的存在,并将javaLikeGet
返回的null
包装成Some
简单而一致的规则是:
如果键k
存在,则get(k)
返回Some[V]
,否则返回None
这比Java的get
在两种完全不同的情况下返回null
的奇怪行为要少得多
这是一个耗资数十亿美元的错误,但Scala不太可能修复它,因为它必须与Java进行互操作。我的猜测是,现在和将来都不会讨论改变这种行为,至少在整个编程环境发生根本性变化之前不会讨论 在这种情况下,我本以为m.get不会返回任何值 为什么?
None
意味着键“Bogus”
不在映射中,但您只需将其放入(值null
)
Java的Map
API在区分“此键的值为null
”和“此键不在映射中”时存在问题,但Scala的不在映射中
在这种情况下,我本以为m.get不会返回任何值
为什么?None
意味着键“Bogus”
不在映射中,但您只需将其放入(值null
)
Java的
Map
API在区分“此键的值为null
”和“此键不在映射中”时存在问题,但Scala的不在映射中。我可以建议稍微澄清一下吗?与其说是Map#get
方法在区分“value is null”和“key not in Map”方面存在问题,不如说是Map#containsKey
总是工作得很好,所以对整个Map API的判断过于苛刻可能有点不公平,这只是Map#get
有点奇怪。我也想到了这一点“例如,一些实现禁止空键和值”:)哦,是吗?抱歉,我没有意识到这一点不一致。那么,让我们把责任归咎于整个API:d之类的事情(如果实现支持空值,空返回还可以指示映射以前将空键与键关联。)“我可以建议你做一个小小的澄清吗?与其说是Map#get
方法在区分“value is null”和“key not in Map”方面存在问题,不如说是Map#containsKey
总是工作得很好,所以对整个Map API的判断过于苛刻可能有点不公平,这只是Map#get
有点奇怪。我也想到了这一点“例如,一些实现禁止空键和值”:)哦,是吗?抱歉,我没有意识到这一点不一致。那么,让我们把责任归咎于整个API:d之类的事情(如果实现支持空值,空返回还可以指示映射以前将空键与键关联。)“我认为我的主要问题是,从语义上讲,scala已经设计了它的地图#变得像选项一样。令人惊讶的是,Option(null)
返回None
,但事实并非如此。@hiroprogator这样想:与Java的get
(称之为javaLikeGet
)相比,Scala的get
类似于def-get(k:k)=if(containsKey(k)){Some(this.likeget(k))}else{None}
而不是def get(k:k)=Option(this.javaLikeGet(k))
。这样做就不那么令人惊讶了。而且它很有效,因为,例如,我对Sca