Reflection Scala枚举和反射
在Java工作了很长一段时间后,我开始对Scala感兴趣。 作为一个学习项目,我尝试复制一个java库,该库存储和检索数据库中的状态对象。 为此,我希望能够指定如下状态对象:Reflection Scala枚举和反射,reflection,scala,enumeration,Reflection,Scala,Enumeration,在Java工作了很长一段时间后,我开始对Scala感兴趣。 作为一个学习项目,我尝试复制一个java库,该库存储和检索数据库中的状态对象。 为此,我希望能够指定如下状态对象: @PersistName("PERSON") case class Person extends Entity { @Persist var id:Long = -1 @Persist @MaxLength(80) var firstName = "" @Persist @MaxLength(80) var
@PersistName("PERSON") case class Person extends Entity {
@Persist var id:Long = -1
@Persist @MaxLength(80) var firstName = ""
@Persist @MaxLength(80) var lastName = ""
@Persist var gender = Gender.Male
@Persist @MaxLength(80) var userName = ""
@Persist @OptionClass(classOf[Date]) var birthDay:Option[Date] = None
}
序列化/取消序列化Person实例的代码使用反射来了解字段的类型,并且对除性别字段以外的所有字段都正常工作。
性别字段是一个枚举,定义为:
object Gender extends Enumeration {
type Gender = Value
val Male,Female,Unknown = Value
}
问题是,我不知道如何使用反射,也不知道如何仅使用Person类创建新的性别值。Scala的枚举很有趣,但case类通常比它有优势:
sealed class Gender
case object Male extends Gender
case object Female extends Gender
这样做的好处是
match
able,如果你测试的是一种性别,而不是另一种性别,Scala甚至会抱怨。而且,它似乎更容易解决您的问题。:-) 可以使用Gender.Male.id获取男性性别值的Int表示。使用Gender.apply()将其取回:
val person = Person()
println("gender = " + person.gender.id)
// prints "gender = 0" on my mac
person.gender = Gender(Gender.Female.id) // have a little operation
println("gender = " + person.gender.id)
// prints "gender = 1" on my mac
因为您正在处理持久性位,所以您所需要做的就是在序列化时存储gender的Int表示,并在反序列化时将其恢复为gender
如果要概括解决方案,请在枚举字段上使用自定义注释。我遇到了相同的问题,找到了一个相当庞大的解决方案,但它可以工作。您需要保留封闭枚举的名称,因为无法使用反射从值中找出真正的枚举
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
val day = WeekDay.Fri
val className = day.getClass.getField("$outer").get(day).getClass.getCanonicalName
// write to database
// className // String
// day.id // Int
现在,当您从数据库中读取
// read from database
// obtain className and id
// enumObject will be WeekDay
val enumObject = Class.forName(className).getField("MODULE$").get().asInstanceOf[Enumeration]
// value will be WeekDay.Fri
val value = enumObject(id)
查看我的:
您需要为其提供字段的scala类型
val enumObject:Type = ... object's scala.Enumeration field
val typ:Type = ... object's scala.Enumeration field's scala type
val isEnum = EnumReflector.isEnumeration(typ)
val reflector = EnumReflector(typ)
val eid = reflector.toID(enumObject)
val enum = reflector.fromID(eid)
assertTrue(eid eq enum)
项目中有一个单元测试来演示它
另外,请参见我在此处对此答案的展开版本:为什么“仅使用Person类”?