reflection - 案例类上的 `productElement(i)`是否使用反射?

标签 reflection scala field product case-class

考虑以下Scala代码段:

case class Foo(v1: String, v2: Int, v3: Any)

def inspect(p: Product) =
  (0 until p.productArity).foreach(i => println(p.productElement(i)))

inspect(Foo("Moin", 77, null))

这里inspect()的调用是否意味着使用反射(以任何方式)?

我希望能够以某种方式访问​​案例类的字段而不必显式引用它们,例如由foo.v1编写,我赞成不需要反射的解决方案,因为我希望它会带来一些开销。

最佳答案

productElement不会使用任何反射。这是一个编译器技巧。在类之前添加大小写不仅会创建一个伴随对象(使用apply方法等,请参见http://www.scala-lang.org/node/258),还会从特征Product扩展类。编译器创建抽象方法productArity和productElement的实现。
scalac -print Foo.scala的输出显示了它:

... case class Foo extends java.lang.Object with ScalaObject with Product {
...
override def productArity(): Int = 3;
override def productElement(x$1: Int): java.lang.Object = {
  <synthetic> val temp6: Int = x$1;
  (temp6: Int) match {
    case 0 => {
      Foo.this.v1()
    }
    case 1 => {
      scala.Int.box(Foo.this.v2())
    }
    case 2 => {
      Foo.this.v3()
    }
    case _ => {
      throw new java.lang.IndexOutOfBoundsException(scala.Int.box(x$1).toString())
    }
  }
};
...
}

如果要不加反射地访问字段,则可以使用特征Product中的productElement方法
scala> case class Foo(v1: String, v2: Int, v3: Any)
defined class Foo

scala> val bar = Foo("Moin", 77, null)
bar: Foo = Foo(Moin,77,null)

scala> bar.productElement(0)
res4: Any = Moin

scala> bar.productElement(1)
res5: Any = 77

scala> bar.productElement(2)
res6: Any = null

关于reflection - 案例类上的 `productElement(i)`是否使用反射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4051271/

相关文章:

c# - 为什么 Assembly.GetTypes() 需要引用?

java - 无法从 .class 读取注释

scala - 匿名函数的参数类型必须是完全已知的。 (SLS 8.5)

scala - 如何将元组声明为函数的返回类型以及如何在 Scala 的调用方代码中访问元组?

scala - 选项列表 : equivalent of sequence in Scala?

c# - 将代码添加到 C# 获取/设置属性而不需要支持字段?

jQuery - 获取 div 中所有图像的 src 并放入字段

java - 从单独的 jar 调用 .asSubclass 时抛出 ClassCastException

mysql 在重复的 FIELD 而不是 KEY 上插入

c# - 在 C# 中将控件和变量的状态从一个窗体复制到另一个窗体