我正在尝试在测试中使用私有特征字段。非常简单的例子:
//Works fine with class A, but not trait A
trait A {
private val foo = "Some string"
}
class Test extends A {
val field = classOf[A].getDeclaredField("foo")
field.setAccessible(true)
val str = field.get(this).asInstanceOf[String]
}
我得到了:
java.lang.NoSuchFieldException:foo at java.lang.Class.getDeclaredField
直播示例here
如何获取此代码段可执行文件?
答案 0 :(得分:4)
A
是一个特征,Scala转换为JVM接口。接口不能有字段,所以没有这样的字段。只有将接口实际混合到一个类中时,才会添加基础字段。
因此,您需要做的第一件事就是将classOf[A]
更改为classOf[Test]
。
第二件事是将getDeclaredField("foo")
更改为.getDeclaredField("A$$foo")
。
答案 1 :(得分:2)
编辑特别感谢@Seth Tisue(投票并接受他)
class Test extends A {
val field:Field = this.getClass.getDeclaredField("A$$foo")
field.setAccessible(true)
println(field.get(this).asInstanceOf[String])
}
" A $$ FOO"获取超类型属性的正确方法是这个,并使用this.getClass
。
我以前不知道它,但是通过这种修正,你的代码将会很好用!
第一个想法:
trait A {
private val foo = "Some string"
}
class Test extends A {
val fields: Seq[Field] = this.getClass.getDeclaredFields.toList
val field = fields.filter(x => {
println(x.getName)
x.getName.contains("foo")
}).head
field.setAccessible(true)
println(field.get(this).asInstanceOf[String])
}
正如您所看到的,当您打印" foo"的名称时变量,不是真的" foo",它是别的东西:
A$A295$A$A295$A$$foo
在我的情况下,这就是你(和我)收到错误的原因
java.lang.NoSuchFieldException: foo at java.lang.Class.getDeclaredField
所以,我现在的想法,我希望有人带来更好的想法,看看是否" foo"在变量名称内" A $ A295 $ A $ A295 $ A $$ foo"所以你可以告诉那个你要找的变量。