解释 - 不涉及反射

Explanation for - No Reflection involved

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

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

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

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

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

一般人在Java或者Scala的语境中说到"reflection"的时候,都是指运行时间反射,但是宏也支持一种反射,所以当我个人谈论推导在这些库中是如何工作的,我尽量小心地指定不涉及 运行time 反射。

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

类型从根本上讲是在 运行 之前拒绝潜在的不良程序,而在 运行 时对类型进行反省会把这一切搞得一团糟(因为 Erik Osheim says、"If you meet a Type in the Runtime, kill it" ).另一方面,在编译时对类型进行自省正是编译器所做的,而宏只是为程序员提供了一种参与该过程的干净方式(或者至少相对干净,与编写编译器插件等相比)。 ).

避免 运行时间反射也可能有性能上的好处,但对我个人而言,这通常是次要问题——我讨厌 运行时间反射,因为我浪费了太多生命调试使用严重依赖 运行时间反射的可怕 Java 库的可怕 Java 代码——不是因为 运行时间反射 可能 我的程序稍慢。

在这种情况下,您应该将 "there is no reflection involved" 阅读为 "there is no runtime reflection involved",这是一种非常冗长的说法(我想即使这样您也不应该相信作者的话, 考虑到喷雾中的所有 getMethods 东西-json).