在scala中,我希望能够说出
val user = Node.create[User](...) // return User object
所以这就是我到目前为止所做的:
def create[T : TypeTag](map: Map[String, Any]) {
val type = typeOf[T]
// create class from type here???
}
我一直在研究如何从泛型类创建类,并发现使用ClassManifest似乎已被弃用。相反,类型标签在这里,所以我能够做类似这种typeOf [T]的事情并且实际上得到了类型......但是我失去了。如果我可以获得该类,那么我可以使用类似class.newInstance的东西并从那里手动设置字段。
问题是:给定一个类型,我可以获得给定类型的类实例吗?
答案 0 :(得分:6)
事实上最简单的方法是使用ClassTag
:
def create[T : ClassTag](map: Map[String, Any]): T = {
val clazz: Class[_] = classTag[T].runtimeClass
clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}
ClassTag
是Java Class
的一个瘦包装器,主要用于数组实例化。
TypeTag
设施更强大。首先,您可以使用它来调用Java反射:
import scala.reflect.runtime.universe._
def create[T: TypeTag](map: Map[String, Any]): T = {
val mirror = runtimeMirror(getClass.getClassLoader) // current class classloader
val clazz: Class[_] = mirror.runtimeClass(typeOf[T].typeSymbol.asClass)
clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}
但是,Scala反射允许实例化类而不回退到Java反射:
def create[T: TypeTag](map: Map[String, Any]): T = {
// obtain type symbol for the class, it is like Class but for Scala types
val typeSym = typeOf[T].typeSymbol.asClass
// obtain class mirror using runtime mirror for the given classloader
val mirror = runtimeMirror(getClass.getClassLoader) // current class classloader
val cm = mirror.reflectClass(typeSym)
// resolve class constructor using class mirror and
// a constructor declaration on the type symbol
val ctor = typeSym.decl(termNames.CONSTRUCTOR).asMethod
val ctorm = cm.reflectConstructor(cm)
// invoke the constructor
ctorm(<constructor arguments here>).asInstanceOf[T]
}
如果要创建具有重载构造函数的类,可能需要更多工作 - 您必须从声明列表中选择正确的构造函数,但基本思想是相同的。您可以阅读有关Scala反射here
的更多信息答案 1 :(得分:1)
有一种方法可以使用反射:运行时反射或宏。关于运行时反射方式,您可以查看my blog post我尝试做的事情,就像您现在尝试做的那样。根据您的需要,对宏使用编译时反射可能是更好的选择。