2013-06-16 2 views
2

Есть компиляции задания времени мне нужно запустить с помощью отражения (заморачиваться вызывающими и вызываемый являются Scala исходных файлов), но я получаю сообщение об ошибке выполнения:Преобразование Java объект (то есть на самом деле Scala Map) в Scala Карту

java.lang.ClassCastException: 
scala.collection.immutable.Map$Map2 cannot be cast 
to scala.collection.immutable.Map 
класс

Отражение:

object jsRoutes { 
    def getRoutesMap: Map[String,String] = {...} 
} 

телефонный код: (loader является Scala 2.10.2 загрузчик классов)

val appLoader = new java.net.URLClassLoader(path, loader) 
val clazz = appLoader.loadClass("controllers.jsRoutes") 
val routesMap = clazz.getMethod("getRoutesMap") 

Любая попытка бросить java.lang.Object ожидаемого типа возвращаемого Map[String,String] результаты выше ClassCastException

routesMap.invoke(new Object).asInstanceOf[Map[String,String]]... 

или не соответствует:

routesMap.invoke(new Object) match { 
    case x: Map[String,String] => ... 
    case _ => println("not matched") 
} 

никогда не слышал о карте $ map2, в выходные class this is Map [String, String], поэтому не уверен, что преобразует возвращаемый тип в вызов отражения.

Может распечатать содержимое файла java.lang.Object (Map) без изменений.

Спасибо за подсказки, this.is.frustrating ;-)

ответ

4

Вы, вероятно, пытаешься бросить через загрузчик классов. Вы не можете этого сделать - каждый загрузчик классов сохраняет свою собственную иерархию (для тех классов, которые не передаются в общий родительский загрузчик). Попробуйте позвонить getClassLoader как на свою возвращенную карту, так и на недавно созданную.

Кстати, Map$Map2 - это просто деталь реализации - подкласс Map для работы с двухэлементными картами. Он отличает нормально нормально:

scala> val m = Map(1->"one", 2 -> "two"): Object 
m: Object = Map(1 -> one, 2 -> two) 

scala> m.getClass 
res0: Class[_ <: Object] = class scala.collection.immutable.Map$Map2 

scala> m.asInstanceOf[scala.collection.immutable.Map[Int,String]] 
res1: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two) 
+0

+1, это правильно, SBT Build.scala предоставляет CL на конце вызова, а затем класс приложения, на который распространяется запрос, имеет собственный CL. Я могу выполнять всю работу в классе приложений, но было бы более целесообразно делать это в Build.scala для этой конкретной задачи. Я не понимаю, что вы имеете в виду, вызвав getCL на возвращенной карте и только что созданном. – virtualeyes

+1

@ virtualeyes - Карты двух разных загрузчиков классов несовместимы друг с другом, даже если класс «тот же» (точное имя и байт-код). «Map $ Map2' вещь - красная селедка - даже если типы были идентичны, вы не смогли бы бросить! См. http://stackoverflow.com/questions/1735714 –

+1

Хотя я не хотел этого услышать, это отличный ответ в том, что я: 1) узнал что-то новое; 2) знайте, что не тратьте больше времени и просто выполняйте работу над концом вещей. Больше не стучать головой, спасибо ;-) – virtualeyes