Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Reflection for getting the field value by its string name and its original type

When trying to get object field by its string name, the value returned, not by correct scala type. As:

import scala.language.reflectiveCalls
import scala.language.implicitConversions

case class Intity(flag: Boolean, id: Int, name: String)
val inty =  Intity(false, 123, "blue")

implicit def reflect(r: AnyRef) = new {
  def get(n:String) = {
    val c = r.getClass.getDeclaredField(n)
    c.setAccessible(true); c}
  def getVal(n: String) = get(n).get(r)
  def getType (n:String) = get(n).getType
 }

then when using this

inty.getType("flag")     // res0: Class[_] = boolean  --not Boolean
inty.getVal("id")        // res1: Object = 123    --Object not Int

Any efficient way of doing the above implementation?

like image 853
ALMEK Avatar asked Nov 25 '16 22:11

ALMEK


People also ask

How do you find the value of field through reflection?

If we want to access Private Field and method using Reflection we just need to call setAccessible(true) on the field or method object which you want to access. Class. getDeclaredField(String fieldName) or Class. getDeclaredFields() can be used to get private fields.

How do you make an object reflection?

We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.

What is reflection for and what information can we get from it?

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.


2 Answers

Not sure, how one can return different types from a single function. But you can infer the correct type of any Class attribute using scala reflect api(s).

import scala.reflect.runtime.{universe => ru}
implicit class ForAnyInstance[T: ru.TypeTag](i: T)(implicit c: scala.reflect.ClassTag[T]) {

    /* a mirror sets a scope of the entities on which we have reflective access */
    val mirror = ru.runtimeMirror(getClass.getClassLoader)

    /* here we get an instance mirror to reflect on an instance */
    val im = ru.runtimeMirror(i.getClass.getClassLoader)

    def fieldInfo(name: String) = {
      ru.typeOf[T].members.filter(!_.isMethod).filter(_.name.decoded.trim.equals(name)).foreach(s => {
        val fieldValue = im.reflect(i).reflectField(s.asTerm).get

        /* typeSignature contains runtime type information about a Symbol */
        s.typeSignature match {
          case x if x =:= ru.typeOf[String] => /* do something */
          case x if x =:= ru.typeOf[Int] => /* do something */
          case x if x =:= ru.typeOf[Boolean] => /* do something */
        }
      })
    }
}

And then invoke it as:

case class Entity(flag: Boolean, id: Int, name: String)
val e = Entity(false, 123, "blue")
e.fieldInfo("flag")
e.fieldInfo("id")
like image 200
phantomastray Avatar answered Sep 28 '22 18:09

phantomastray


You can do something similar at compile time with shapeless.

scala> import shapeless._
import shapeless._

scala> val inty = Intity(false, 123, "blue")
inty: Intity = Intity(false,123,blue)        

scala> val intyGen = LabelledGeneric[Intity].to(inty)
intyGen: shapeless.::[Boolean with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("flag")],Boolean],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("id")],Int],shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.HNil]]] = false :: 123 :: blue :: HNil

scala> import shapeless.record._
import shapeless.record._

scala> intyGen.get('flag)
res10: Boolean = false

scala> intyGen.get(Symbol("id"))
res11: Int = 123
like image 23
Jasper-M Avatar answered Sep 28 '22 18:09

Jasper-M