怎么取出类的泛型类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么取出类的泛型类型相关的知识,希望对你有一定的参考价值。

参考技术A ParameterizedType parameterizedType = (ParameterizedType)this.getClass().getGenericSuperclass();

entityClass= (Class<T>)(parameterizedType.getActualTypeArguments()[0]);本回答被提问者和网友采纳

通过给定的泛型类型 Scala 获取类的伴随对象

【中文标题】通过给定的泛型类型 Scala 获取类的伴随对象【英文标题】:Get companion object of class by given generic type Scala 【发布时间】:2012-02-28 16:12:40 【问题描述】:

我要做的是创建一个函数,该函数将采用泛型类并在其中使用静态方法(对不起,Java 语言,我的意思是它的伴随对象的方法)。

trait Worker def doSth: Unit

class Base

object Base extends Worker

// this actually wouldn't work, just to show what I'm trying to achieve
def callSthStatic[T that companion object is <: Worker](implicit m: Manifest[T]) 
  // here I want to call T.doSth (on T object)
  m.getMagicallyCompanionObject.doSth

有什么想法吗?

【问题讨论】:

【参考方案1】:

A gist by Miles Sabin可能会给你一个提示:

trait Companion[T] 
  type C
  def apply() : C


object Companion 
  implicit def companion[T](implicit comp : Companion[T]) = comp()


object TestCompanion 
  trait Foo

  object Foo 
    def bar = "wibble"

    // Per-companion boilerplate for access via implicit resolution
    implicit def companion = new Companion[Foo] 
      type C = Foo.type
      def apply() = Foo
    
  

  import Companion._

  val fc = companion[Foo]  // Type is Foo.type
  val s = fc.bar           // bar is accessible

如果使用 Scala 2.9.x,则应使用 -Ydependent-method-types 标志编译。

【讨论】:

我添加了实际的 Gist 内容 - Gist 可能会消失,并且只有链接才有资格作为评论。 我在“implicit def partner[T] (隐式comp:Companion [T])= comp()”与scala 2.9.1。我做错了吗? :-) 我会在括号中添加,如果类型 Foo 是可见的,那么它的伴生对象也是可见的,所以虽然这看起来很漂亮,但我认为它在实践中没有用。 这是一个不错的技巧。我必须阅读一些有关依赖方法类型的信息,但这似乎有效!谢谢 如果没有“每个同伴样板”部分,有什么方法可以让它工作?【参考方案2】:

您可以使用反射来获取伴生类及其实例,但这依赖于 Scala 内部结构,这些内部结构可能会在遥远的(?)未来发生变化。当您获得 AnyRef 时,没有类型安全性。但是没有必要为你的类和对象添加任何隐式。

def companionOf[T : Manifest] : Option[AnyRef] = try
  val classOfT = implicitly[Manifest[T]].erasure
  val companionClassName = classOfT.getName + "$"
  val companionClass = Class.forName(companionClassName)
  val moduleField = companionClass.getField("MODULE$")
  Some(moduleField.get(null))
 catch 
  case e => None


case class A(i : Int)

companionOf[A].collectcase a : A.type  => a(1)
// res1: Option[A] = Some(A(1))

【讨论】:

谢谢,反射会解决问题...直到 scala 版本更新,因为伴生对象的名称不承诺以这种方式保留。 嗯,没错。但我认为命名不会很快改变,因为这个约定至少从早期的 Scala 2.x 天开始就持续了。【参考方案3】:

当我忘记如何执行此操作并且答案对我来说不是百分百满意时,我会一直点击此页面。以下是我如何处理反射:

val thisClassCompanion = m.reflect(this).symbol.companion.asModule
val structural = m.reflectModule(thisClassCompanion)
                  .instance.asInstanceOf[def doSth: Unit]

您可能需要验证该类实际上有一个伴生对象或伴生对象。asModule 将抛出反射异常不是模块

更新:为清楚起见添加了另一个示例:

    object CompanionUtil 

  import scala.reflect.runtime.currentMirror => cm

  def companionOf[T, CT](implicit tag: TypeTag[T]): CT = 
    Try[CT] 
      val companionModule = tag.tpe.typeSymbol.companion.asModule
      cm.reflectModule(companionModule).instance.asInstanceOf[CT]
    
  .getOrElse(throw new RuntimeException(s"Could not get companion object for type $tag.tpe"))


【讨论】:

什么是 m?你能举一个完整的例子吗?我正在寻找可以像这样使用的东西:abstract class Whatever[T] = val companion = companionOf[T] m 是当前镜像,我只是将它重命名为 import import scala.reflect.runtime.currentMirror => m 请注意,CT 是伴随对象的类型,即T.type,例如companionOf[Foo, Foo.type] 其中Foo 是具有伴随对象的类的名称。 根据答案,这里有一个获取指定类对象的伴生对象类型引用的方法:def companionOf[CT](clazz: Class[_]): CT = import scala.reflect.runtime.currentMirror =&gt; cm Try[CT] val companionModule = cm.classSymbol(clazz).companion.asModule cm.reflectModule(companionModule).instance.asInstanceOf[CT] .getOrElse(throw new RuntimeException(s"Could not get companion object for $clazz")) 【参考方案4】:

根据Miquel的回答,这里有一个获取指定类对象的伴生对象类型引用的方法:

  /**
    * Returns the companion object type reference for the specified class
    *
    * @param clazz The class whose companion is required
    * @tparam CT Type of the companion object
    * @return The type of the relevant companion object
    */
  def companionOf[CT](clazz: Class[_]): CT = 
    import scala.reflect.runtime.currentMirror => cm
    Try[CT] 
      val companionModule = cm.classSymbol(clazz).companion.asModule
      cm.reflectModule(companionModule).instance.asInstanceOf[CT]
    .getOrElse(throw new RuntimeException(s"Could not get companion object for $clazz"))
  

【讨论】:

以上是关于怎么取出类的泛型类型的主要内容,如果未能解决你的问题,请参考以下文章

java 定义泛型类的问题

当类的泛型相关时,如何在两个泛型类之间创建类似子类型的关系

泛型类的基本使用

类型为指向另一个类的对象的泛型类 - 不工作 [关闭]

Java中的泛型的问题?

泛型程序设计---泛型类的定义