问题
I am trying to get a type-safe way of converting the result of parsing a JSON string. I want to check whether a field is Map[String, any] or a plain string. My first attempt is
def test(x:Any) = {
x match {
case m:Map[String,Any] => ...
...
}
This causes "non-variable type argument String in type pattern Map[String,Any] is unchecked since it is eliminated by erasure"
Looking through the document of TypeTag and ClassTag, I could not find a good way to accomplish that. The following code does not cause the warning, but I wonder why it works.
type StringMap = Map[String,Any]
def test(x:Any) = {
x match {
case m:StringMap => ...
...
}
回答1:
It was a bug. It's fixed in 2.11:
scala> type StringMap = Map[String, Any]
defined type alias StringMap
scala> (Map(4 -> true): Any) match {
| case m: StringMap => true
| case _ => false
| }
<console>:10: warning: non-variable type argument String in type pattern scala.collection.immutable.Map[String,Any] (the underlying of StringMap) is unchecked since it is eliminated by erasure
case m: StringMap => true
^
res0: Boolean = true
The reason it doesn't work is that you can't tell, due to erasure, what the type arguments were. If you want to be sure it's a Map[String, Any] instead of some other kind of map, you have to go check every key and make sure it's a String.
case m: Map[_,_] if m.keySet.forall(_.isInstanceOf[String]) =>
m.asInstanceOf[Map[String,Any]]
回答2:
It's impossible to check the type parameters, but
I want to check whether a field is Map[String, any] or a plain string
is easy:
x match {
case s: String => ...
// you can add cases for numbers, etc. here
case m: Map[_, _] => ... m.asInstanceOf[Map[String, Any]]
}
Looking through the document of TypeTag and ClassTag, I could not find a good way to accomplish that.
Tags are created by the compiler using static type information, so in your case you'll only have class or type tag of Any.
来源:https://stackoverflow.com/questions/23155288/in-scala-how-to-test-the-type-of-an-any-object-against-a-type-with-type-param