Java枚举的介绍本身在本文中并未提及,相关资料很多。本文将讲述Java枚举的一些技巧和注意事项。
Java枚举可以定义属性和常量。比如很常见的一周枚举。
从周一到周日的七个枚举常量值用英语定义。通常,大多数序列化工具会以常量名称字符串的形式将其序列化。的常量名称字符是字符串“MONDAY”,可以通过()函数访问。
这个已定义的枚举除了英文常量之外没有其他信息。但是,我们可以通过在枚举中自定义属性来向枚举添加有意义的附加信息:
添加int类型的value属性来说明枚举(序列化字段)的值,并添加String类型的label属性来说明枚举的说明。如有必要,您可以添加多个描述性属性,例如:
枚举常量名:其常量名为name,字符串表达式为‘MONDAY’。name属性是私有的,可以通过name()方法访问。
这里的一个坑是name()方法有一个final修饰符,这意味着你不能重写它。由于Java的机制,您可以定义一个名称属性字段来覆盖枚举默认名称,如下所示:
这可能会给你一种错觉,以为name()方法会返回你定义的值,比如: ()会返回' MAN ',但实际上它会返回' MALE '。因为枚举常量名称(name())不能被重写,并且在enum中定义的名称是私有的,所以它总是采用字符串表格形式初始化常量名称。
记住,这一点非常重要!因为大多数序列化工具调用枚举的。name()方法来获取用于序列化的字符串,如Jackson、Dubbo…….
因此,为了避免不必要的歧义,建议您在自定义属性时不要使用name作为属性名称。
以杰克逊为例。如果碰巧你的枚举使用常量名的序列化已经满足了业务需求,那么你不需要做任何设置。
如果您想用自定义属性的值进行序列化,那么您可以在属性名中添加JsonValue注释,Jackson将使用它的值进行序列化。比如前面定义的WeekEnumvalue属性,添加JsonValue注释后,Jackson会将其序列化为数字1。
Jackson为枚举提供了四种序列化方法:
通过获取枚举常数的索引是最不推荐的方法。序列化的ordinal(),因为它根据枚举中常数定义的顺序从0开始从上到下计数。在代码重构和进化的过程中,可能会不小心改变顺序,导致序列化值混乱,失去兼容性!
当你使用杰克逊的全局配置来调用。name(),toString()和。ordinal()来序列化枚举,然后你想反序列化,一切就好了。但是,当使用JsonValue注释进行序列化时,Jackson仍将使用默认配置进行反序列化,这意味着使用JsonValue注释指定的属性将不会用于反序列化。要反序列化JsonValue指定的属性,需要定制一个反序列化器,并通过Jackson的模块机制注册它。很简单:
虽然很简单,但是代码还是很多的。这里就不贴代码了。完整的代码可从以下网址获得:
更多关于杰克逊的信息,请阅读我的另一篇文章:《JSON 之 Jackson》。
如何在数据库访问层使用Java枚举,比如Mybatis,将在后面的文章中介绍。可以先收藏我的一个系列文章《CRUDer 的自我修养:PostgreSQL、JDBC、MyBatis、R2DBC》。