繁体   English   中英

模式匹配Map中的Scala类型擦除Map [String,Int]

[英]Scala type erasure in pattern matching Map[String, Int]

Scala 2.10 ,编译器警告给定的代码:

  private def getStrFromOpt[T](opt: Option[T]): String = opt match {
    case Some(s: String) => s
    case Some(i: Int) => i.toString()
    case Some(l: Long) => l.toString()
    case Some(m: Map[String, Int]) => m map ({ case (k, v) =>
      "(" + k + ", " + v + ")" }) mkString ("(", ", ", ")")
    case _ => ""
  }

消息non-variable type argument String in type pattern Map[String,Int] is unchecked since it is eliminated by erasure: case Some(m: Map[String, Int]) ...的消息non-variable type argument String in type pattern Map[String,Int] is unchecked since it is eliminated by erasure: case Some(m: Map[String, Int]) ...的消息non-variable type argument String in type pattern Map[String,Int] is unchecked since it is eliminated by erasure: case Some(m: Map[String, Int]) ...

我如何摆脱这个警告? 如果我想在匹配中包含Map[String, MyObj] ,该怎么Map[String, MyObj] -如何通过参数化Map区分这两种情况?

您可以使用Scala注释@unchecked禁止显示警告,对于第二个问题,建议您使用Scala反射-TypeTag。 我正在使用Scala 2.11.4,下面是示例代码FYI。

import scala.reflect.runtime.{ universe => ru }
import scala.reflect.runtime.universe.{ typeTag, TypeTag }

object MapType extends App {
  def getTypeTag[T: TypeTag](t: T) = typeTag[T].tpe
  def getTypeTag[T: TypeTag] = ru.typeOf[T]

  // context bound T: ru.TypeTag cause typeOf 
  // requires implicit parameter
  def getStrFromOpt[T: TypeTag](opt: Option[T]): String = {
    opt match {
       case Some(s: String) => s
       case Some(i: Int) => i.toString()
       case Some(l: Long) => l.toString()
       case Some(m: Map[String, Int] @ unchecked) 
         if getTypeTag[T] =:= getTypeTag[Map[String, Int]] => "Int Map"
       case Some(m: Map[String, String] @ unchecked) 
         if getTypeTag[T] =:= getTypeTag[Map[String, String]] => "String Map"
       case _ => ""
     }
  }

  // "Int Map"
  println(getStrFromOpt(Some(Map("a" -> 2, "b" -> 3)))) 
  // "String Map"
  println(getStrFromOpt(Some(Map("a" -> "2", "b" -> "3")))) 
}

实际上,Scala就像Java一样使用泛型的擦除模型。 因此,在运行时不会保留有关类型参数的信息。

def isIntMap(x: Any) = x match {
   case m: Map[Int, Int] => true
   case _ => false
}

对于上面的代码,Scala编译器无法确定m是否为Map [Int,Int]。 因此, isIntMap(Map("a"-> "b"))返回true,这似乎是不直观的。 为了提醒您运行时行为,Scala编译器发出了该未经检查的消息。

但是,Array是一个异常,它的元素类型与元素值一起存储。

def isIntArray(x: Any) = x match {
  case a: Array[String] => "yes"
  case _ => "no"
} 

scala> isIntArray(Array(3))
res1: String = no

scala> isIntArray(Array("1"))
res2: String = yes

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM