使用构造函数参数通过反射实例化对象 [英] instantiate object with reflection using constructor arguments

查看:46
本文介绍了使用构造函数参数通过反射实例化对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何用反射实例化一个案例类对象.是否有任何支持?我最接近的是查看 scala.reflect.Invocation,但这似乎更适合执行作为对象一部分的方法.

I'm trying to figure out how to instantiate a case class object with reflection. Is there any support for this? The closest I've come is looking at scala.reflect.Invocation, but this seems more for executing methods that are a part of an object.

case class MyClass(id:Long, name:String)

def instantiate[T](className:String)(args:Any*) : T = { //your code here }

接近我正在寻找的 API.

Is close to the API I'm looking for.

任何帮助将不胜感激.

推荐答案

scala> case class Foo(id:Long, name:String)
defined class Foo

scala> val constructor = classOf[Foo].getConstructors()(0)
constructor: java.lang.reflect.Constructor[_] = public Foo(long,java.lang.String)

scala> val args = Array[AnyRef](new java.lang.Integer(1), "Foobar")
args: Array[AnyRef] = Array(1, Foobar)

scala> val instance = constructor.newInstance(args:_*).asInstanceOf[Foo]
instance: Foo = Foo(1,Foobar)

scala> instance.id
res12: Long = 1

scala> instance.name
res13: String = Foobar

scala> instance.getClass
res14: java.lang.Class[_] = class Foo

目前在 Scala 中没有太多的反射支持.但是您可以退回到 Java 反射 API.但是有一些障碍:

Currently there is not much reflection support in Scala. But you can fall back to th Java Reflection API. But there are some obstacles:

  • 您必须创建一个 Array[AnyRef] 并在包装类(java.lang.Integer、java.lang.Character、java.lang.Double, ...)

newInstance(Object ... args) 得到一个 Object 的可变参数数组,所以你应该用 :_ 给类型推断器一个提示*

newInstance(Object ... args) gets an varargs array of Object, so you should give the type inferer a hint with :_*

newInstance(...) 返回一个 Object,因此您必须使用 asInstanceOf[T] 将其转换回>

newInstance(...) returns an Object so you have to cast it back with asInstanceOf[T]

我最接近你的 instantiate 函数是这样的:

The closest I could get to your instantiate function is this:

def instantiate(clazz: java.lang.Class[_])(args:AnyRef*): AnyRef = {
  val constructor = clazz.getConstructors()(0)
  return constructor.newInstance(args:_*).asInstanceOf[AnyRef]
}

val instance = instantiate(classOf[MyClass])(new java.lang.Integer(42), "foo")
println(instance)           // prints: MyClass(42,foo)
println(instance.getClass)  // prints: class MyClass

您无法从泛型类型获取 get 类.Java 擦除它(类型擦除).

You cannot get the get class from a generic type. Java erases it (type erasure).

2012 年 9 月 20 日

三年过去了,可以改进 instantiate 方法以返回正确类型的对象.

Three years on, the instantiate method can be improved to return a properly typed object.

def instantiate[T](clazz: java.lang.Class[T])(args:AnyRef*): T = {
  val constructor = clazz.getConstructors()(0)
  return constructor.newInstance(args:_*).asInstanceOf[T]
}

参见 http://www.nabble.com/How-do-I-get-the-class-of-a-Generic--td20873455.html

这篇关于使用构造函数参数通过反射实例化对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆