【问题标题】:In Scala, fetched value of declared field cast to its class-declared type在 Scala 中,获取的声明字段的值转换为其类声明的类型
【发布时间】:2014-01-13 11:30:46
【问题描述】:

想请教如何在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 知道类型。

【问题讨论】:

  • 如果你使用反射来获取它的值,你怎么能指望它在没有演员表的情况下工作?编译器不知道名为 "i" 的字段的类型(也不知道它是否真的存在)。

标签: scala reflection types casting field


【解决方案1】:

f.get(c)静态类型Object,因为它可以是任何类和任何字段。但是,在运行时它将返回一个 IntegerInt 的 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 来获取它的类型并使您的逻辑依赖于它。

【讨论】:

  • 非常感谢,阿列克谢;不过,在这种情况下,类型将是 inferrable 仅来自类声明...
  • 调用f.getType 传递Class[_] = int ;因此,如何将其转换为 Int。
  • asInstanceOf,如前所述。
  • 再次感谢,Alexey;询问如何处理已使用的已定义类型?
  • @ecoe 我还编辑了答案以展示如何避免需要java.lang 类。
猜你喜欢
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 2015-03-15
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多