我正在编写 Java(不是 Scala)代码,其中我有一个 Java Class
引用,指的是 Scala 类型 T
:
trait T {}
我现在想通过Java反射发现Java Class
引用,以及对应于object T
的单例实例,然后调用其中的方法伴随对象。
object T {
def someMethod : String = "abc";
}
我对生成的 Scala 代码进行了逆向工程,以编写以下 Java 代码:
Class<?> traitClass = ...;
Class<?> companionClass = Class.forName(traitClass.getName() + "$");
Field module = companionClass.getField("MODULE$");
Object companion = module.get(companionClass);
String abc = (String) companionClass.getMethod("someMethod").invoke(companion);
这看起来不是很健壮——它可能会随着 future 的 Scala 编译器随时改变。有没有更稳健的方法?我也愿意调用 Scala API(从 Java)来发现伴随实例。
最佳答案
您编写的代码适用于顶级(包拥有的)同伴。它也适用于嵌套类/特征对象对的基本情况,但有些情况下简单的 name + $
方案不成立。这是一个例子:
class C {
class D
object D
def foo() {
class K
object K
}
}
这会生成类文件 C
、C$D
、C$D$
、C$K$2
和 C$K$3$
。
虽然编码可能会在未来的任何时候改变,但它在很长一段时间内没有改变,也不打算改变。我刚试过 2.5.0,除了方法中嵌套的类之外,类名是一样的。
如果您可以控制 Scala 类,最简单的方法是添加一个方法 def companion = T
到 trait T
。
另一种选择是使用 Scala 反射 API:
scala> import scala.reflect.runtime.{universe => ru}
scala> val m = ru.runtimeMirror(getClass.getClassLoader)
scala> val d = classOf[C$D]
d: Class[C$D] = class C$D
scala> m.runtimeClass(m.classSymbol(d).companionSymbol.asModule.moduleClass.asClass)
res16: Class[_] = class C$D$
但是对于嵌套在方法中的类,这也不能像预期的那样工作:
scala> val k = classOf[C$K$2]
k: Class[C$K$2] = class C$K$2
scala> m.classSymbol(k).companionSymbol
res2: reflect.runtime.universe.Symbol = <none>
请注意,在 SO 上搜索“scala reflection companion”也会产生几个结果(并显示一些问题)。
关于java - 通过 Java 反射找到 Scala 类型的伴随对象的可靠方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36068089/