scala:java.lang.reflect.Field的可序列化替代方案

scala:java.lang.reflect.Field的可序列化替代方案,scala,serialization,reflection,apache-spark,case-class,Scala,Serialization,Reflection,Apache Spark,Case Class,假设User是一个case类,它保存有关用户的信息: case class User(name: String, age: Int) 给定一个字段名(例如“name”或“age”),我想返回一个提取此字段的函数(无需再次解析字段名)。简言之,我需要这个来工作: val u = User(name = "john",age = 44) val func = extractFunctionFromFieldName("name") // returns func: User => Any f

假设
User
是一个case类,它保存有关用户的信息:

case class User(name: String, age: Int)
给定一个字段名(例如
“name”
“age”
),我想返回一个提取此字段的函数(无需再次解析字段名)。简言之,我需要这个来工作:

val u = User(name = "john",age = 44)
val func = extractFunctionFromFieldName("name") // returns func: User => Any
func(u) // return "john"
def extractFunctionFromFieldName(s: String): User => Any = {
  val f = classOf[User].getDeclaredField(s)
  f.setAccessible(true)
  u: User => f.get(u)
}
在阅读有关反思的文章时,我得到了这样的东西:

val u = User(name = "john",age = 44)
val func = extractFunctionFromFieldName("name") // returns func: User => Any
func(u) // return "john"
def extractFunctionFromFieldName(s: String): User => Any = {
  val f = classOf[User].getDeclaredField(s)
  f.setAccessible(true)
  u: User => f.get(u)
}
问题是此函数不可序列化,因为
java.lang.reflect.Field
不可序列化

有什么建议或选择吗

备注/更多背景资料:

  • 字段列表远不止是
    {name,age}
    ,而且还在不断增长。这就是为什么我想避免硬编码
  • 使用
    productElement
    应该不会出现序列化问题,因为字段被替换为数字。但我知道产品元素的顺序没有保证
  • 顺便说一句,我需要它是可序列化的,因为我正在使用ApacheSpark
使用productElement应该不会出现序列化问题,因为字段将替换为数字。但我知道产品元素的顺序没有保证

有。对于case类,它们的顺序与参数相同

或者,您可以创建一个类,该类仍然可以是一个函数(此处更一般;如果不需要,则更改为仅使用
User
应该很容易):

这将仅在第一次应用该字段时初始化该字段,因此在反序列化该字段一次后可以多次应用,而无需重复
getDeclaredField
调用

我最初没有注意到这是问题所要求的,因此我最初给出的另一个解决方案不适用:您可以在函数内部移动
f
(在您的情况下,创建函数对象并被它“捕获”时,
f
就已经知道了,这就是为什么它必须被序列化的原因):


谢谢你的回答。但正如我在问题中所说的,我希望函数避免每次调用函数时都需要再次解析包含字段名的字符串。假设函数生成一次,但应用了十亿次。这正是我给出上一个解决方案的原因。它只会在构造函数中创建<代码> f>代码>,即在反序列化的情况下。您还应该考虑<代码>产品代码< /C>解决方案,它根本不涉及反射。“阿米尔,我把解决方案固定了一点,现在它应该可以工作了。使上一个
extractFunctionFromFieldName
可序列化的事实是您将
f
标记为transient。但出于同样的原因,在反序列化后不能使用该对象,因为
f
不再具有其值。