为什么 Manifest 被弃用了?什么时候应该使用 ClassTag,什么时候应该使用 TypeTag

2024-02-09

我有几个问题Manifest and TypeTag。据我了解,JVM 不了解泛型并删除类型。所以我不能这样做

def factoryForAll[T] = new T // will not compile. Runtime doesn't know what T is

Scala 编译器可以使用以下命令将有关类型的信息传输到运行时Manifest(现已弃用)。Manifest有类似的方法erasure其中包含有关类型的信息。所以我可以执行以下操作来创建通用类型 T 的对象

def factoryForall[T](implicit ev:Manifest[T]) = ev.erasure.newInstance

scala> factoryForAll[String]
res1:Any=""

scala> class C
defined class C

scala> factoryForAll[C]
res5: Any = C@52cb52bd

问题 1 - 有趣的是,它不适用于 Int (或 Float)?为什么?

scala> factoryForAll[Int]
java.lang.InstantiationException: int

问题 2 - 为什么 Manifest 被弃用?据我了解,新版本TypeTag信息更丰富,但不明白Manifest有什么缺点

问题 3 - Scala 2.12 仍然有Manifest class (https://www.scala-lang.org/api/current/scala/reflect/Manifest.html https://www.scala-lang.org/api/current/scala/reflect/Manifest.html). If Manifest都不好,为什么Scala还有它?该文档提到使用Manifest创造Arrays通用类型,但数组可以通过以下方式实现ClassTag以及。那么为什么 Scala 仍然有Manifest?

scala> def makeArray[T](len:Int)(implicit ev:ClassTag[T]) = new Array[T](len)
makeArray: [T](len: Int)(implicit ev: scala.reflect.ClassTag[T])Array[T]

scala> makeArray[String](4)
res39: Array[String] = Array(null, null, null, null)

scala> makeArray[Int](4)
res40: Array[Int] = Array(0, 0, 0, 0)

scala> val al = makeArray[List[Int]](2)
al: Array[List[Int]] = Array(null, null)

scala> al(0) = List(1)

scala> al(1) = List(2,3)

来到TypeTag,有3种类型。参考Scala文档(http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html)和 Medium 上的教程(https://medium.com/@sinisaluc/overcoming-type-erasure-in-scala-8f2422070d20 https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20), 我明白那个TypeTag and ClassTag有不同的用例。 ClassTag 无法区分超出第一级擦除的类型。

//method to extract a type from a collection
def extractType[T](col:Iterable[Any])(implicit ev:ClassTag[T]) = {
val it =col.iterator
while (it.hasNext) {
val el = it.next
el match {
case x:T => println("got T")
case _ => println("not T")
}}}

extractType: [T](col: Iterable[Any])(implicit ev: scala.reflect.ClassTag[T])Unit

scala> extractType[Int](List(1,2,3,"hello"))
got T
got T
got T
not T

scala> extractType[List[Int]](List(List(1),List(2),List(3),List("hello")))
got T
got T
got T
got T //this should be not T

问题4:如果ClassTag无法区分第一级擦除,为什么当我尝试添加擦除时会出现以下错误String in a List[Set[Int]]. Isn't Int erased?

scala> def makeArray[T](len:Int)(implicit ev:ClassTag[T]) = new Array[T](len)
makeArray: [T](len: Int)(implicit ev: scala.reflect.ClassTag[T])Array[T]

scala> val al = makeArray[List[Set[Int]]](2)
al: Array[List[Set[Int]]] = Array(null, null)

scala> al(0) = List(Set(2))

scala> al(1) = List(Set("2"))
<console>:28: error: type mismatch;
 found   : String("2")
 required: Int
       al(0) = List(Set("2"))
                        ^

问题 5 - 为什么在前面的例子中extractType[List[Int]](List(List(1),List(2),List(3),List("hello"))),Scala无法区分String from Int但它区分了al(0) = List(Set(2)) and al(1) = List(Set("2"))

问题 6 - 如何更改extractType函数使我可以检查嵌入类型。我知道我必须使用 TypeTag,但我不知道如何检查集合中元素的类型。

def extractType[T](col:Iterable[Any])(implicit ev:TypeTag[T]) = {
    println("class is "+ev.mirror.runtimeClass) //I suppose in TypeTag, runtime is here
    val it =col.iterator
    while (it.hasNext) {
    val el = it.next
    el match {
        case x:T => println("got T") //this doesn't compile. What should I check for?
        case _ => println("not T")
    }}}

问题一:Int and Float不由 JVM 中的类表示(尽管它们有相应的Class对象),更不用说具有无参数构造函数的对象了。尽管forAll从名称上看,这适用于非常有限的类型。

问题2:Manifest混淆了哪些担忧ClassTag and TypeTag分离。

问题3:如果你看一下来源Manifest, 它说

// TODO undeprecated until Scala reflection becomes non-experimental 
// @deprecated("use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") 

问题4/5:这个错误来自静态类型al: Array[List[Set[Int]]]。没有提供运行时信息ClassTag or TypeTag参与。

问题6:只使用标准库不行。但看无形的 https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#type-safe-cast.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Manifest 被弃用了?什么时候应该使用 ClassTag,什么时候应该使用 TypeTag 的相关文章

随机推荐

  • ASP.NET 启动 Web 性能分析

    我正在尝试确定 ASP NET 应用程序初始启动时间过长 恕我直言 的原因 该应用程序使用各种第三方库 以及许多我确信可以整合的参考资料 但是 我正在尝试识别 并分配责任 这些 dll 以及它们对扩展启动过程的贡献有多大 到目前为止 启动时
  • 嵌套数组上的 MongoDB $elemMatch 投影

    我有一个这样的集合 摘要 id summaryid locations id loc1 datacenters id dc1 1 clusters id cl1 1 servers
  • 如何在 AngularJS 中从 $http.get 返回图像

    在我的控制器中 我调用一个返回承诺的服务 var onComplete function data scope myImage data 在我的服务中 我通过将 url 直接传递给图像本身来调用以获取图像 return http get h
  • C++ 头文件的解析器可以使用标准 Linux 工具提取函数吗?

    有这样的事吗 我需要从头文件中提取 C 函数及其使用的所有参数 如果我能使用标准的 Linux 程序就好了 您可以使用 Understanding 4 C 这是一个前端工具 可以浏览源代码并为源代码生成指标 它还具有强大的API 允许您编写
  • 更改 Coldfusion 上附件的文件名

    我在用着cfmailparam将文件附加到电子邮件 我正在从数据库中获取文件名和路径 通常 附加文件具有唯一的名称 但我可以通过查询数据库表中的以下列来获取其原始文件名 ASSET FILE NAME 独特的名字 ASSET REAL NA
  • 浮点数学有问题吗?

    考虑以下代码 0 1 0 2 0 3 gt false 0 1 0 2 gt 0 30000000000000004 为什么会出现这些不准确的情况 Binary 浮点 https en wikipedia org wiki Double p
  • 使用 Hive 中的 Month() 获取 MM 中的月份

    Select from concat YEAR DATE SUB MAX Column name 60 MONTH DATE SUB MAX Column name 60 01 The month 仅产生single九月之前的月份数字 即一
  • clang-format AlignAfterOpenBracket 列表参数

    这个帖子 https stackoverflow com questions 21966530 clang format always break if params dont fit问了一个类似的问题 当参数太多时如何修改格式 我非常喜欢
  • 如何解释 Devel::Leak 的输出

    我已经跑了Devel Leak http search cpan org ni s Devel Leak 0 03 Leak pm在我的程序中 我不明白它给我的输出 首先 我看到它正在打印一个指针列表 我可以在数组中获取该列表吗 然后我可以
  • 如何检查 IP 地址是否在特定子网内

    我有一个格式为 10 132 0 0 20 的子网和来自 ASP Net 请求对象的 IP 地址 是否有 NET 框架函数可以检查 IP 地址是否在给定子网内 如果不能的话 怎么办呢 位操作 我猜 看一眼使用 C 计算 IP 地址 http
  • 如何让“page-break-inside:void”与“flex-wrap:wrap”很好地配合

    我想得到page break inside avoid以使用多行 Flexbox 布局的形式工作 使用flex wrap wrap 目的只是为了避免打印时破坏表单问题 这适用于单行 Flexbox 或不使用 Flexbox 查看打印预览ht
  • 如何调用或重新启动MathJax?

    我需要 MathJax 重新检查我的所有页面 我的意思是 当页面创建后 一切都很棒 但我需要在 window onload 之后调用它来重新解析页面 因为其内容同时发生了变化 我该怎么做这样的事呢 See http docs mathjax
  • Spring依赖注入:注入接口的所有实例

    如果可能的话 如何使用实现特定接口的所有其他 Spring bean 集合来配置 Spring bean 示例 我想连接CarFactory带有实现以下功能的 bean 列表的 beanCarManufacturer界面 Inject pr
  • 如何从 SwiftUI 中的函数返回按钮?

    我需要根据一些参数动态创建一个按钮 func buildButton parameter Parameter gt Button switch parameter case Parameter Value1 return Button ac
  • Bootstrap 4 轮播不起作用?

    我有以下 BS4 轮播代码 使用本教程制作的 但是代码不起作用 显示了第一张图像 但我不知道出于什么原因轮播不受控制 并且在任何情况下都不会转到下一张图像 可能的解决方案是什么 div class container div class r
  • nm 输出中的“_GLOBAL__sub_I_”是什么意思?

    当我尝试解决静态链接中的问题时 我遇到了一些问题 GLOBAL sub I 符号名称前面的前缀 尽管我使用过 但它以这种形式出现nm demangle C 我偶然发现了这个答案 如何找到全局静态初始化 https stackoverflow
  • Docker 名称解析暂时失败 [Errno -3]

    我正在关注码头工人教程 https docs docker com get started part2 我必须使用以下方法构建应用程序 docker build t friendlyhello 它到达第 4 步 暂停后我收到此错误 Step
  • Node.js 中 require 的正确方法是什么?

    我刚刚开始使用 Node js 和 Electron 并且在文档和示例代码中都看到了有关如何请求模块的各种方法 具体来说 我正在尝试遵循this https medium com developers writing building a
  • 如何获取 ASP.NET MVC 中 HttpResponse 的引用?

    我正在调用一个第三方库 它需要System Web HttpResponse 我看到我有一个HttpResponseBase 但不是HttpResponse就像网络表单一样 有没有办法获得HttpResponse Using MVC 3 E
  • 为什么 Manifest 被弃用了?什么时候应该使用 ClassTag,什么时候应该使用 TypeTag

    我有几个问题Manifest and TypeTag 据我了解 JVM 不了解泛型并删除类型 所以我不能这样做 def factoryForAll T new T will not compile Runtime doesn t know