Как получить класс _: любой - PullRequest
4 голосов
/ 29 июня 2010

Я завернул сообщение и хотел бы записать, какое сообщение я завернул.

val any :Any = msg.wrappedMsg
var result :Class[_] = null

Единственное решение, которое я смог найти, - это сопоставить все:

result = any match {
  case x:AnyRef => x.getClass
  case _:Double => classOf[Double]
  case _:Float  => classOf[Float]
  case _:Long   => classOf[Long]
  case _:Int    => classOf[Int]
  case _:Short  => classOf[Short]
  case _:Byte   => classOf[Byte]
  case _:Unit   => classOf[Unit]
  case _:Boolean=> classOf[Boolean]
  case _:Char   => classOf[Char]
}

Интересно, есть ли лучшее решение? Следующие 2 подхода не работают: (

result = any.getClass //error
// type mismatch;  found   : Any  required: ?{val getClass: ?} 
// Note: Any is not implicitly converted to AnyRef.  
// You can safely pattern match x: AnyRef or cast x.asInstanceOf[AnyRef] to do so.
result = any match {
  case x:AnyRef => x.getClass
  case x:AnyVal => /*voodoo to get class*/ null // error
}
//type AnyVal cannot be used in a type pattern or isInstanceOf

Ответы [ 3 ]

7 голосов
/ 29 июня 2010

Вы можете безопасно вызывать .asInstanceOf[AnyRef] по любому значению Scala, которое будет содержать примитивы:

scala> val as = Seq("a", 1, 1.5, (), false)
as: Seq[Any] = List(, 1, 1.5, (), false)

scala> as map (_.asInstanceOf[AnyRef])
res4: Seq[AnyRef] = List(a, 1, 1.5, (), false)

Оттуда вы можете позвонить getClass.

scala> as map (_.asInstanceOf[AnyRef].getClass)
res5: Seq[java.lang.Class[_]] = List(class java.lang.String, class java.lang.Int
eger, class java.lang.Double, class scala.runtime.BoxedUnit, class java.lang.Boo
lean)

Протестировано с 2.8.0.RC6, я не знаю, это работало в 2.7.7.

Определенно новым в 2.8 являются сопутствующие объекты для классов, производных от AnyVal. Они содержат удобные box и unbox методы:

scala> Int.box(1)
res6: java.lang.Integer = 1

scala> Int.unbox(res6)
res7: Int = 1
3 голосов
/ 16 января 2014

Начиная с версии scala 2.10.0, getClass доступен для Any (а не только для AnyRef), поэтому вам больше не нужно делать какие-либо искажения, и вы можете просто выполнить any.getClass.

Обратите внимание, что вы все равно должны быть готовы обработать двойное отношение между примитивными типами и их коробочной версией.Например, getClass для целочисленного значения вернет либо java.lang.Integer.TYPE (класс примитивного типа Int), либо classOf[java.lang.Integer] в зависимости от статического типа значения:

scala> 123.getClass
res1: Class[Int] = int

scala> val x : Int = 123
x: Int = 123

scala> x.getClass
res2: Class[Int] = int

scala> val x: AnyVal = 123
x: AnyVal = 123

scala> x.getClass
res3: Class[_] = class java.lang.Integer

scala> val x: Any = 123
x: Any = 123

scala> x.getClass
res4: Class[_] = class java.lang.Integer
3 голосов
/ 29 июня 2010

Разве кастинг не поможет, как предложено в сообщении об ошибке?


scala> val d:Double = 0.0
d: Double = 0.0

scala> d.asInstanceOf[AnyRef].getClass
res0: java.lang.Class[_] = class java.lang.Double
...