【问题标题】:Scala type erasure in pattern matching Map[String, Any]模式匹配 Map[String, Any] 中的 Scala 类型擦除
【发布时间】:2018-04-12 07:40:10
【问题描述】:

我使用的是 scala 版本 2.12.3,当我在控制台代码中测试一些模式匹配时:

val d: Any = Map("1" -> "2", "3" -> 4)
d match {
    case map: Map[String, Any] => println(map)
    case _ => println("should not be here")
}

我收到了一些警告,例如 <console>:14: warning: non-variable type argument String in type pattern scala.collection.immutable.Map[String,Any] (the underlying of Map[String,Any]) is unchecked since it is eliminated by erasure

我在谷歌上搜索过这个警告,几乎所有的答案都被告知 scala 运行时间会在进行模式匹配时擦除类型,回答这个问题似乎是合理的,但是当我使用以下代码时:

val e = Map("1" -> "2", "3" -> 4)
e match {
    case map: Map[String, Any] => println(map)
    case _ => println("should not be here")
}

没有关于类型擦除的警告,那么这两种模式匹配有什么区别,请解释一下什么时候会发生类型擦除,谢谢!

【问题讨论】:

  • 为什么首先介绍Any问题?
  • @cchantep 我首先介绍Any问题,因为我对模式匹配的类型擦除感到很困惑,第二个代码块让我对运行时类型擦除有点怀疑。
  • 最好解决第一个问题,而不是试图解决失去类型安全的这种后果

标签: scala pattern-matching type-erasure


【解决方案1】:

匹配: Map[String, Any] 的问题在于,实际上只能在运行时检查您是否获得了Map。所以例如

val d: Any = Map(0 -> 0)
d match {
    case map: Map[String, Any] => println(map)
    case _ => println("should not be here")
}

匹配成功并打印地图。在第二种情况下,e 的静态类型已经是Map[String, Any]。所以编译器“知道”你不能得到任何其他类型的 Map 并且没有问题需要警告。

但是类型擦除仍然会发生。这意味着您实际上可以e 中获得除Map[String, Any] 之外的其他内容,但只能通过以某种方式向编译器撒谎或忽略其他警告。在这种情况下,匹配仍然成功。例如

val e = Map(0 -> 0).asInstanceOf[Map[String, Any]]
e match {
    case map: Map[String, Any] => println(map)
    case _ => println("should not be here")
}

【讨论】:

    【解决方案2】:

    这在Programming in Scala中有解释

    第一次收到警告,因为 d 被强制为 Any 类型。第二次编译器将 e 的类型推断为 Map[String, Int] ,这是模式匹配的第一种情况表达式。编译器在编译时就知道类型,因此无需警告。

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 2015-12-03
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多