我想问一下如何在Scala中实现以下功能。考虑
scala> case class C(i:Int)
defined class C
scala> val c = C(1)
c: C = C(1)
鉴于感兴趣的领域,在这种情况下
scala> val fname = "i"
fname: String = i
我们希望在c中检索字段i的原始值和类型。
第一个天真的尝试包括以下内容,
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
然而,
scala> val a:Int = f.get(c)
<console>:11: error: type mismatch;
found : Object
required: Int
val a:Int = f.get(c)
^
换句话说,如何在c(*)
中获取i的Int值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
...
并且对于不一定是Int类型,请考虑D中的字段j,
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
...
非常感谢......
摘要
鉴于
scala> f.get(c)
res1: Object = 1
和
scala> f.getType
res3: Class[_] = int
如何获得
val a = 1
其中a是Int类型,只知道来自f.getType的类型。
答案 0 :(得分:2)
f.get(c)
的静态类型是Object
,因为它可以是任何类和任何字段。但是,在运行时它将返回Integer
(Int
的Java包装类)。您可以使用
f.get(c).asInstanceOf[Int]
或
f.getInt(c)
如果您事先知道要求Int
字段。如果不这样做,您可以进行模式匹配:
f.get(c) match {
case i: Integer => ...
case l: java.lang.Long => ...
case s: String => ...
// etc.
}
// actually compiles to same code, but avoids the need to use boxed classes
(f.get(c): Any) match {
case i: Int => ...
case l: Long => ...
case s: String => ...
// etc.
}
请注意,采用的分支取决于字段的实际值,而不是其类型;例如对于val f: Any = ""
,将case s: String
分支。
或者您可以使用f.getType
获取其类型并使您的逻辑依赖于此。