从类型scala中获取类

jos*_*inm 2 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???
}
Run Code Online (Sandbox Code Playgroud)

我一直在研究如何从泛型类创建类,并发现使用ClassManifest似乎已被弃用.相反,类型标签在这里,所以我能够做类似这个typeOf [T]的东西,实际上得到类型..但后来我迷路了.如果我可以获得该类,那么我可以使用类似class.newInstance的东西并从那里手动设置字段.

问题是:给定一个类型,我可以获得给定类型的类实例吗?

Vla*_*eev 6

事实上最简单的方法是使用ClassTag:

def create[T : ClassTag](map: Map[String, Any]): T = {
  val clazz: Class[_] = classTag[T].runtimeClass
  clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}
Run Code Online (Sandbox Code Playgroud)

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]
}
Run Code Online (Sandbox Code Playgroud)

但是,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]
}
Run Code Online (Sandbox Code Playgroud)

如果你想创建一个带有重载构造函数的类,它可能需要更多工作 - 你必须从声明列表中选择正确的构造函数,但基本思想是相同的.您可以在此处阅读有关Scala反射的更多信息