【问题标题】:Get a class from a type scala从类型 scala 中获取一个类
【发布时间】:2014-07-31 01:19:23
【问题描述】:

在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 之类的东西并从那里手动设置字段。

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

【问题讨论】:

    标签: scala


    【解决方案1】:

    其实最简单的方法是使用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

    【讨论】:

      【解决方案2】:

      有一种使用反射的方法:运行时反射或在宏中。关于运行时反射方式,您可以查看my blog post,我在其中尝试执行您现在正在尝试执行的操作。根据您的需要,将编译时反射与宏一起使用可能是更好的选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-15
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 2015-05-27
        • 1970-01-01
        相关资源
        最近更新 更多