Scala 2.10 introduced a new reflection API (see here for an in-depth overview) which is much closer to the actual type system than the old Manifests were - in fact the compiler uses TypeTags itself. And it’s not hard to use as we’ll see. One reason why Scala provides reflection additional to Java’s reflection API is that the JVM erases generic types. As a motivation let’s see how generic types get erased at runtime:

  case class A[T]
  println(A[String].isInstanceOf[A[String]]) // true
  println(A[String].isInstanceOf[A[Int]])    
  // true aswell - doesn't sounds right, no? 
  // that's because the type of T gets erased at runtime...

Scala 2.10 introduces TypeTag which brings us the compile-time information about the generic type T to the runtime:

  import scala.reflect.runtime.universe._
    case class B[T: TypeTag] {
      val tpe = typeOf[T]
  }
  println(B[String].tpe == typeOf[String]) // true
  println(B[String].tpe == typeOf[Int])    // false

  //and this also works for nested parameterised types:
  println(B[List[String]].tpe == typeOf[List[String]]) //true
  println(B[List[String]].tpe == typeOf[List[Int]])    //false

Another use case for the reflection API we just had at work is to get all members of an object that are of a given type. We define a customer specific configuration in objects that drives our whole system - from the Swagger API documentation all the way down to how we persist the data in Cassandra and do our filters. The code below grabs all members of an object that are subtypes of Field, gets their generic type T and checks if they mix in a given trait Required. Scala’s runtime mirrors allow us to lookup the symbols and types for a given instance at runtime - pretty neat!

  import scala.reflect.runtime.universe._
  case class Field[T: TypeTag] {
    val tpe = typeOf[T]
  }
  trait Required //can be mixed into Field to mark it as required
  
  object SomeClass extends BaseClass {
    val stringField = Field[String]
    val requiredIntField = new Field[Int] with Required
  }

  abstract class BaseClass {
    val typeMirror = runtimeMirror(this.getClass.getClassLoader)
    val instanceMirror = typeMirror.reflect(this)
    val members = instanceMirror.symbol.typeSignature.members
    def fieldMirror(symbol: Symbol) = instanceMirror.reflectField(symbol.asTerm)

    def fields = members.filter(_.typeSignature <:< typeOf[Field[_]])
    // filters all members that conform to type Field[_], i.e. also subclasses of Field
  }

  SomeClass.fields.foreach { symbol 
    val name = symbol.name.toString.trim
    val required = symbol.typeSignature <:< typeOf[Required]
    val tpe = SomeClass.fieldMirror(symbol).get match {
      case field: Field[_]  field.tpe
    }
    println(s"field: $name; type=$tpe; required: $required")
    /** prints:
     *  field: requiredIntField; type=Int; required: true
     *  field: stringField; type=String; required: false
     */
  }

Credit goes to my colleague Felix Geller who discovered most of this first!