为什么Scala集合的contains方法不要求传入与元素类型匹配的参数?
问题:显式声明元素类型为Int的Vector调用contains传入其他类型参数为何可以正常编译?
示例代码:
scala> val x: Vector[Int] = Vector(1,2,3) val x: Vector[Int] = Vector(1, 2, 3) scala> x.contains("hello") val res4: Boolean = false scala> x.contains(List(Map("anything" -> 3.14))) val res5: Boolean = false
补充说明:本问题和另一种集合元素类型被推断为Any的常见场景不同,后者是集合本身的元素类型就是Any,入参符合类型要求,本问题中Vector的元素类型是显式指定为Int的。
解答
这是Scala 2标准库集合的设计特性导致的,核心原因如下:
Vector属于协变集合,定义为Vector[+A],如果contains方法直接将入参声明为元素类型A,会违反Scala的型变规则:方法参数属于逆变位置,不能使用协变的类型参数。为了规避这个限制,Scala 2的序列类集合统一将contains的入参类型设置为Any,因此不管传入什么类型的参数,编译都不会报错。- 运行时执行
contains逻辑时,会先对比入参和集合元素的类型,类型不匹配会直接返回false,不会抛出运行时异常,所以示例中的两个调用都能正常运行得到false结果。
这个设计长期存在容易隐藏类型不匹配bug的问题,社区通常推荐用静态检查工具(比如Wartremover)拦截这类不安全调用,Scala 3也对contains方法的签名做了优化,大部分场景下已经支持编译期校验入参和集合元素类型的匹配性。
内容的提问来源于stack exchange,提问作者mitchus
相关产品推荐
相关产品推荐

