scalareflectiontypessymbolsmirror

The relationship between Type Symbol and Mirror of Scala reflection


The Scala reflection is really complicated. It contains type symbol and mirror. Could you tell me the relationship between them?


Solution

  • When working with the Scala Reflection API you encounter a lot more types that what you're used to if you've used the Java Reflection API. Given an example scenario where you start with a String containing a fully qualified class name of a class, these are the types you are likely to encounter:

    So putting an example together reflecting the description above, this is how you would search for fields, invoke constructors and read a val, given a String with the fully qualified class name:

    // Do runtime reflection on classes loaded by current ClassLoader
    val currentMirror: universe.Mirror = scala.reflect.runtime.currentMirror
    
    // Use symbols to navigate to pick out the methods and fields we want to invoke
    // Notice explicit symbol casting with the `.as*` methods.
    val classSymbol: universe.ClassSymbol = currentMirror.staticClass("com.example.Foo")
    val constructorSymbol: universe.MethodSymbol = classSymbol.primaryConstructor.asMethod
    val fooSymbol: Option[universe.TermSymbol] = classSymbol.toType.members.find(_.name.toString == "foo").map(_.asTerm)
    
    // Get mirrors for performing constructor and field invocations
    val classMirror: universe.ClassMirror = currentMirror.reflectClass(classSymbol)
    val fooInstance: Foo = classMirror.reflectConstructor(constructorSymbol).apply().asInstanceOf[Foo]
    val instanceMirror: universe.InstanceMirror = currentMirror.reflect(fooInstance)
    
    // Do the actual invocation
    val fooValue: String = instanceMirror.reflectField(fooSymbol.get).get.asInstanceOf[String]
    println(fooValue) // Prints the value of the val "foo" of the object "fooInstance"