I would like to ask how to achieve the following in Scala. Consider
scala> case class C(i:Int)
defined class C
scala> val c = C(1)
c: C = C(1)
Given a field of interest, in this case
scala> val fname = "i"
fname: String = i
we would like to retrieve the original value and type of field i in c.
A first, naive, attempt included the following,
scala> val f = c.getClass.getDeclaredField(fname)
f: java.lang.reflect.Field = private final int C.i
scala> f.setAccessible(true)
scala> f.getType
res3: Class[_] = int
However,
scala> val a:Int = f.get(c)
<console>:11: error: type mismatch;
found : Object
required: Int
val a:Int = f.get(c)
^
Put another way, how to fetch the Int value for i in c (*)
scala> :type -v case class C(i:Int)
// Type signature
AnyRef
with Product
with Serializable {
val i: Int <----------------------- (*)
private[this] val i: Int
def <init>(i: Int): C
def copy(i: Int): C
...
and for not necessarily Int type, consider field j in D,
scala> case class C(i:Int)
defined class C
scala> case class D(j:C)
defined class D
scala> :type -v case class D(j:C)
// Type signature
AnyRef
with Product
with Serializable {
val j: C
private[this] val j: C
def <init>(j: C): D
def copy(j: C): D
...
Thanks very much...
In Summary
Given
scala> f.get(c)
res1: Object = 1
and
scala> f.getType
res3: Class[_] = int
how to get
val a = 1
where a is of type Int, and knowing the type only from f.getType.
The static type of
f.get(c)
isObject
, because it can be any class and any field. However, at the runtime it will return anInteger
(the Java wrapper class forInt
). You can cast it by usingor
if you know in advance that you are calling for an
Int
field. If you don't, you can pattern match:Note that the taken branch depends on the actual value of the field, not on its type; e.g. for
val f: Any = ""
thecase s: String
branch will be taken.Or you can use
f.getType
to get its type and make your logic depend on that.