【问题标题】:Explanation for - No Reflection involved解释 - 不涉及反射
【发布时间】:2016-02-08 08:43:25
【问题描述】:

我有一个非常简单的问题。这不仅适用于 spray-json,而且我已经阅读了 argonaut 和 circe 的类似声明。所以请赐教。

在 spray-json 中,我遇到了 There is no reflection involved 的声明。我理解基于类型类的方法,如果用户提供 JsonFormat 那么一切都很好。但是,当涉及到使用 DefaultJsonProtocol 时,这种说法是否也是正确的?

因为我们在看this的时候,可以看到clazz.getMethodsclazz.getDeclaredFields等的用法,这不就是反射的用法吗?当然,感谢object#apply,我们不需要担心与使用反射的 Java 世界不同的设置。但至少对于阅读字段名称,我不明白如何忽略反射。

【问题讨论】:

    标签: scala spray-json


    【解决方案1】:

    我对spray-json不是很熟悉,所以我不会为它关于反射的说法辩护,这似乎与你指向的ProductFormats的部分不一致。

    我确实更了解 circe 和 Argonaut 以及 argonaut-shapeless 和 Play JSON,所有这些都使用一种反射来为案例类和其他用户定义的类型派生编解码器。重要的一点是这些库不使用 runtime 反射——它们通过 Scala 的宏系统在编译时确定所需的字段名称和其他信息。

    通常人们在 Java 或 Scala 的上下文中谈论“反射”时,他们指的是运行时反射,但宏也支持一种反射,所以当我个人谈论这些库中的派生如何工作时,我尽量做到小心指定不涉及运行时反射。

    您可以争辩说编译时反射(或元编程,或任何您想称呼它的名称)比运行时反射要好得多。它可能会使您的代码更复杂,并且很容易被滥用,但它不会引入与运行时反射相同的脆弱性,并且不会破坏您以与运行时反射相同的方式推理代码的能力做。如果您了解宏的作用(这是一个很大的if),您在运行时永远不会感到惊讶。

    类型本质上是在你运行它们之前拒绝潜在的不良程序,并且在运行时对类型的自省会混淆这一切(如Erik Osheim says,“如果你在运行时遇到一个类型,就杀死它”)。另一方面,编译时对类型的自省正是编译器所做的,而宏只是为程序员提供了一种参与该过程的干净方式(或者至少相对干净,与编写编译器插件等相比)。 )。

    避免运行时反射也可能带来性能优势,但对我个人而言,这通常是次要的问题 - 我讨厌运行时反射,因为我浪费了太多时间来调试糟糕的 Java 代码,这些代码使用了严重依赖的糟糕的 Java 库关于运行时反射——不是因为运行时反射可能让我的程序稍微变慢。

    在这种情况下,您应该将“不涉及反射”理解为“不涉及运行时反射”,这是一种非常冗长的说法(即使这样,您也不应该相信作者的话,我猜,考虑到 spray-json 中的所有 getMethods 内容)。

    【讨论】:

    • 谢谢。我的直觉确实首先想到了宏。我什至看过李浩毅发推文说在 json 库中使用运行时反射。您能否在same kinds of fragility as runtime reflection 上多说些什么。是不是因为必须派生类型并相应地设置(尤其是空值)引起关注?
    猜你喜欢
    • 1970-01-01
    • 2012-06-08
    • 2012-06-23
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    相关资源
    最近更新 更多