Question

I have a number of use cases for this, all around the idea of interop between existing Java libraries and new Scala Code. The use case I've selected is the easiest I think.

Use Case:

I working on providing a JUnit Runner for some scala tests (so that I can get my lovely red / green bar in Eclipse) The runner needs to have a constructor with a java class as a parameter. So in Scala I can do the following:

class MyRunner(val clazz: Class[Any]) extends Runner {
  def getDescription(): Description 
  def run(notifier: RunNotifier)
}

When I use either

@RunWith(MyRunner)
object MyTestObject 

or

@RunWith(MyRunner)
class MyTestClass

then the runner is indeed instantiated correctly, and is passed a suitable class object

Unfortunately what i want to do now is to "get hold of" the object MyTestObject, or create a MyTestClass, which are both Scala entities. I would prefer to use Scala Reflection, but I also want to use the standard Junit jar.

What I have done

The following Stackover flow questions were educational, but not the same problem. There were the nearest questions I could find

The discussion on Environments, Universes and Mirrors in http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html was good, and the similar documents on other scala reflection also helped. Mostly through it is about the Scala reflection.

I browsed the Scaladocs, but my knowledge of Scala reflection wasn't enough (yet) to let me get what I wanted out of them.

Edit: As asked here is the code of the class that is being created by reflection

@RunWith(classOf[MyRunner])
object Hello2 extends App {

  println("starting")

  val x= "xxx"
}

So the interesting thing is that the solution proposed below using the field called MODULE$ doesn't print anything and the value of x is null

Was it helpful?

Solution

This solution works fine if you want to use plan old java reflection. Not sure if you can use scala reflection given all you will have is a Class[_] to work with:

object ReflectTest {
  import collection.JavaConversions._
  def main(args: Array[String]) {    
    val fooObj = instantiate(MyTestObject.getClass())
    println(fooObj.foo)
    val fooClass = instantiate(classOf[MyTestClass])
    println(fooClass.foo)
  }

  def instantiate(clazz:Class[_]):Foo = {
    val rm = ru.runtimeMirror(clazz.getClassLoader())
    val declaredFields = clazz.getDeclaredFields().toList
    val obj = declaredFields.find(field => field.getName() == "MODULE$") match{
      case Some(modField) => modField.get(clazz)
      case None => clazz.newInstance()
    }
    obj.asInstanceOf[Foo]
  }
}

trait Foo{
  def foo:String
}

object MyTestObject extends Foo{
  def foo = "bar"
}

class MyTestClass extends Foo{
  def foo = "baz"
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top