One of the most questionable features of the Java runtime is for certain type erasure. It renders type parameters a mere compiler feature with no benefits at runtime.

Scala basically suffers from the same problem, by default the compiler strips away all type information from parametrized types. But fortunately there is a simple way to request the compiler to generate some meta information which can be obtained at runtime: Just add the predefined type Manifest as context bound to the type parameter like this:

class Test[A : Manifest]

The runtime class can then be obtained like this:

val runtimeClass = manifest[A].runtimeClass

You can see a context bound as a has a relation of the type parameter. In fact it’s a shorthand for an implicit constructor argument. One could also have written:

class Test[A](implicit m: Manifest[A]) 

But that’s not so handy if more than one type parameter is involved.

Below a full example how the runtime class could be used in a base class for a CRUD repository:

abstract class CRUDRepository[E <: Serializable](implicit m: Manifest[E]){

  val runtimeClass = m.runtimeClass
  println(s"Runtime class: $runtimeClass")

  @PersistenceContext 
  @BeanProperty
  var entityManager: EntityManager = _

  def findById(id: long) = this.entityManager.find(
    runtimeClass, id)

  def findAll() = this.entityManager.createQuery(
    s"from ${runtimeClass.getName}").getResultList()

  def persist(entity: A) = this.persist(entity)

  //...

}

case class Person(name: String)

@Repository
class PersonRepository extends CRUDRepository[Person]

Please note, that context bounds do not work with Traits, since they cannot have constructors.

Leave a Reply

Your email address will not be published. Required fields are marked *


*