加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何使用新的反射API来判断数组的组件类型是否符合类型

发布时间:2020-12-16 09:49:11 所属栏目:安全 来源:网络整理
导读:如果我有方法…… def arrayConformsTo[A](as: Array[_]) = ??? …我可以根据需要在A中添加Context Bounds.我希望此方法查看Array的组件类型,如果这是A的子类型,则返回true.例如: arrayConformsTo[Int](Array(1,2,3)) //returns truearrayConformsTo[String
如果我有方法……

def arrayConformsTo[A](as: Array[_]) = ???

…我可以根据需要在A中添加Context Bounds.我希望此方法查看Array的组件类型,如果这是A的子类型,则返回true.例如:

arrayConformsTo[Int](Array(1,2,3)) //returns true

arrayConformsTo[String](Array(1,3)) //returns false

在2.10之前,这将完成如下:

def arrayConformsTo[A: Manifest](as: Array[_]) = 
  ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A]

但是,这现在编译了弃用警告

<console>:8: warning: method <:< in trait ClassManifestDeprecatedApis is deprecated: Use scala.reflect.runtime.universe.TypeTag for subtype checking instead
       ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A]
                                                         ^
<console>:8: warning: value ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead
       ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A]

我对此的第一个猜测如下:

scala> def arrayConformsTo[A: reflect.ClassTag](as: Array[_]) =
     | reflect.ClassTag(as.getClass.getComponentType) <:< implicitly[reflect.ClassTag[A]]

但这也给出了弃用警告

<console>:8: warning: method <:< in trait ClassManifestDeprecatedApis is deprecated: Use scala.reflect.runtime.universe.TypeTag for subtype checking instead
       reflect.ClassTag(as.getClass.getComponentType) <:< implicitly[reflect.ClassTag[A]]
                                                  ^

它告诉我使用TypeTag.但是怎么样?这甚至是一个有效的问题反思?

附录:虽然它对AnyVal不起作用,但它似乎对我需要的东西合理地工作:

scala> def arrayConformsTo[A: reflect.ClassTag](as: Array[_]) =
     | implicitly[reflect.ClassTag[A]].runtimeClass isAssignableFrom as.getClass.getComponentType

解决方法

scala反射api肯定是一个迷宫,但至少它是全面的:

import scala.reflect.runtime.{universe => ru}
def arrayConformsTo[A: ru.TypeTag](as: Array[_]) = {
  val mirror = ru.runtimeMirror( getClass.getClassLoader )
  val classSym = mirror.classSymbol( as.getClass.getComponentType )
  classSym.toType <:< implicitly[ru.TypeTag[A]].tpe
}

REPL测试:

scala> arrayConformsTo[Float]( Array[Float]() )
res9: Boolean = true

scala> arrayConformsTo[Int]( Array[Float]() )
res10: Boolean = false

scala> arrayConformsTo[AnyVal]( Array[Float]() )
res11: Boolean = true

scala> arrayConformsTo[AnyVal]( Array[Float]() )
res12: Boolean = true

scala> arrayConformsTo[Any]( Array[Float]() )
res13: Boolean = true

scala> arrayConformsTo[Any]( Array[Float]() )
res14: Boolean = true

scala> arrayConformsTo[AnyRef]( Array[Float]() )
res15: Boolean = false

scala> arrayConformsTo[AnyRef]( Array[Float]() )
res16: Boolean = false

(由于完整性原因,由OP编辑)

另一个解决方案(不需要scala-reflect.jar),虽然不能保留Float<:< AnyVal是true属性是使用ClassTag作为提取器:

scala> def arrayConformsTo[A](as: Array[_])(implicit arrayOfA: ClassTag[Array[A]]) 
     | = as match {
     |     case arrayOfA(_) => true
     |     case _           => false
     |   }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读