Reflection Read-Access to Scala Vars

Scala does not provide a special reflection API so we have to use the usual java reflection.

Scala provides the @BeanProperty annotation to automatically create setter and getter (although these are not usable by Scala code). In this case Scala and Java makes no difference.

If I want to access simple property fields directly I have to be aware that you can not access Scalas val properties by a Field reflection class.

F. e. I want to access the following Java class:

public class SomeJavaTestFilter {
    public BigInteger creatorId;
    public String nameTxt;
}

and the following Scala class:

class SomeFilter {
  var creatorId:BigInteger = _
  var nameTxt:String = _
}

Javap decompiles the Scala class to:

public class com.jpaextension.test.SomeFilter extends java.lang.Object implements scala.ScalaObject{
    public com.jpaextension.test.SomeFilter();
    public void nameTxt_$eq(java.lang.String);
    public java.lang.String nameTxt();
    public void creatorId_$eq(java.math.BigInteger);
    public java.math.BigInteger creatorId();
}

Scala class objects

  • are implementing ScalaObject
  • are using Methods for read access

So one possible flexible property read access Object could be:

object ReflectionUtil {

  private val scalaObject = Class.forName("scala.ScalaObject")

  private def getField[T](o:AnyRef, fieldName:String):T = {
    val f = o.getClass.getField(fieldName)
    f.get(o).asInstanceOf[T]
  }

  def getPropertyField[T](o:AnyRef, fieldName:String, array:Array[Class[_]] = Array[Class[_]]()):T = {
    if(scalaObject.isAssignableFrom(o.getClass)) {
      val method = o.getClass.getMethod(fieldName, array:_*)
      method.invoke(o, array:_*).asInstanceOf[T]
    }
    else
      getField(o, fieldName)
  }

}

Comments are closed.