在Java工作了很长时间后,我开始对Scala产生兴趣。 作为一个学习项目,我试图复制一个存储和检索数据库中的状态对象的java库。 为此,我希望能够像这样指定一个状态对象:
@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类创建一个新的Gender值。
答案 0 :(得分:4)
Scala的枚举很有意思,但案例类经常比它有优势:
sealed class Gender
case object Male extends Gender
case object Female extends Gender
这具有match
能力的优势,如果您测试一种性别而不测试另一种性别,Scala甚至会抱怨。并且,它似乎更容易解决您的问题。 : - )
答案 1 :(得分:0)
您可以使用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
由于您正在处理持久性位,因此您需要做的就是在序列化时存储性别的Int表示,并在反序列化时将其还原为Gender。
如果要概括解决方案,请在“枚举”字段中使用自定义注释。
答案 2 :(得分:0)
我遇到了同样的问题,发现了一个相当庞大的解决方案,但它确实有效。您需要保留封闭枚举的名称,因为无法使用反射从值中找出真正的枚举。
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)
答案 3 :(得分:0)
查看我的EnumReflector:
您需要为其提供该字段的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)
项目中有一个单元测试来演示它。
另外,请在此处查看此答案的扩展版本:Is it possible to use reflection to find the actual type of a field declared to be a Scala Enumeration subtype?