如何使用反射从Scala访问Java静态成员?

时间:2016-04-28 15:26:38

标签: java scala reflection h2o

我有一个自动生成的Java类,我在Scala应用程序中使用它。类似的东西:

public class Model123123 extends GenModel {
  public int nclasses() { return 4; }

  // Names of columns used by model.
  public static final String[] NAMES = NamesHolder_Model123123.VALUES;

我可以创建像这样的实例

val model = Class
          .forName("Model123123")
          .newInstance()
          .asInstanceOf[GenModel]

我想访问此Java类的静态成员。我可以直接这样做,如下:

Model123123.NAMES

但不明白如何通过反思来做到这一点。我试过了:

scala> Class.forName("Model123123").NAMES
<console>:10: error: value NAMES is not a member of Class[?0]
              Class.forName(model_name).NAMES

scala> model.getClass.NAMES
<console>:11: error: value NAMES is not a member of Class[?0]
              model.getClass.NAMES

我不太了解Java或scala反射,所以我有点迷失。我试图通过反射来做这个,因为我将有许多类,它们是同一个父类的子类,我想在运行时动态地更改类。

谢谢

2 个答案:

答案 0 :(得分:2)

应该可以这样:

val clazz = Class.forName("Model123123")
val field = clazz.getDeclaredField("NAMES")
val value = field.get(null).asInstanceOf[Array[String]]

我们得到课程并以与我们对非静态字段相同的方式请求字段。获得该字段后,我们可以通过调用get方法获取它的值。 null参数意味着我们没有传递它应该从中获取值的任何实例(因为它是静态成员)。最后,我们必须手动将类型转换为我们期望的类型,因为此时类型信息会丢失。

如果您需要更新静态字段的值,可以将其设为

field.set(null, Array[String]("name1", "name2"))

我们再次传递null,因为我们不需要在某个特定实例上设置它,因为它是类成员。

它基本上只是scala语言中使用的java反射。另一种方法是使用scala镜像 - http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html

答案 1 :(得分:1)

在您的情况下,最好的方法是将模型实例转换为通用接口hex.genmodel.GenModel,然后您可以轻松调用getNames方法来访问名称。

无需使用反射来访问静态成员。