请考虑以下代码:
class Foo(var name: String = "bar")
现在我尝试通过反射来获取它的值和正确的类型:
val foo = new Foo
val field = foo.getClass.getDeclaredField("name")
field.setAccessible(true)
//This is where it doesn't work
val value = field.get(????)
我尝试过像field.get(foo)这样的东西,但这只返回一个java.lang.Object但没有String。基本上我需要正确的类型,因为我想在它上面调用一个方法(例如toCharArray)。
建议的方法是什么?
答案 0 :(得分:6)
正如其他人所提到的,反射方法会返回Object
,因此您必须进行投射。您可能更好地使用Scala编译器为字段访问创建的方法,而不必更改私有字段的可见性。 (我甚至不确定名称私有字段是否保证与访问者方法的名称相同。)
val foo = new Foo
val method = foo.getClass.getDeclaredMethod("name")
val value = method.get(foo).asInstanceOf[String]
答案 1 :(得分:4)
getDeclaredField
是java.lang.Class
的方法。
您必须将foo.getDeclaredField("name")
更改为foo.getClass.getDeclaredField("name")
(或classOf[Foo].getDeclaredField("name")
)才能获得该字段。
您可以在课程getType
中使用Field
方法获取该类型,但它不会对您有所帮助,因为它会返回Class[_]
。鉴于您知道该类型是String,您始终可以使用field.get(foo).asInstanceOf[String]
答案 2 :(得分:1)
AFAIK,反射始终与Object一起使用,您必须自己投射结果。
答案 3 :(得分:0)
看起来不可能做我想做的事情而不用手工尝试所有可能的类型e。克。
o match {
case I if o.isInstanceOf[Int] => val i = I.asInstanceOf[Int]
case F if o.isInstanceOf[Float] => val f = I.asInstanceOf[Float]
case S if o.isInstanceOf[String] => val s = I.asInstanceOf[String]
case OF if o.getGenericType.toString == "scala.Option<java.lang.Float>" => val of = OF.asInstanceOf[Option[Float]]
.
.
.
好吧,让我们希望将来会有一种语言可以运作......
答案 4 :(得分:0)
这就是人们可以获得字段名列表及其案例类价值的方法:
首先,使用反射,获取字段信息如下 -
val TUPLE2_OF_FIELDNAME_TO_GETTERS = typeOf[<CLASS>].members
.filter(!_.isMethod)
.map(x => (x.name.toString, classOf[<CLASS>].getDeclaredMethod(x.name.toString.trim)))
如何使用它?
getFieldNameAndValue(obj: <CLASS>): Seq[(String, String)] {
var output = Seq[(String, String)]()
for(fieldToGetter <- TUPLE2_OF_FIELDNAME_TO_GETTERS) {
val fieldNameAsString = fieldToGetter._1
val getter = fieldToGetter._2
val fieldValue = getter.invoke(obj).toString
output += (fieldName, fieldValue)
}
}
答案 5 :(得分:0)
foo.getClass.getDeclaredField("name").getString(foo)
如果您想避免使用asInstanceOf
,应该可以使用。 get*
适用于各种类型