枚举类型定义
-
简单枚举
public enum Day0 { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; } 复制代码
-
向枚举中自定义属性和方法
(1) 自定义了一个day属性
@Getter public enum Day1 { MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY("Friday"), SATURDAY("Saturday"), SUNDAY("Sunday"); private String day; Day1(String day) { this.day = day; } } 复制代码
(2) 自定义了2个属性
@Getter public enum Day { MONDAY(0, "Monday"), TUESDAY(1, "Tuesday"), WEDNESDAY(2, "Wednesday"), THURSDAY(3, "Thursday"), FRIDAY(4, "Friday"), SATURDAY(5, "Saturday"), SUNDAY(6, "Sunday"); private int val; private String day; Day(int val, String day) { // 枚举类型构造函数必为private的,不需指定 this.val = val; this.day = day; } } 复制代码
枚举类型实现原理
在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了java.lang.Enum类。
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
// 枚举的常量名,例如MONDAY, TUESDAY
private final String name;
public final String name() {
return name;
}
// 枚举的序号,按顺序从0开始
private final int ordinal;
public final int ordinal() {
return ordinal;
}
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
public String toString() {
return name;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
...
}
复制代码
javap反编译枚举类型Day:
public final class com.tplink.test.pojo.Day extends java.lang.Enum<com.tplink.test.pojo.Day> {
public static final com.tplink.test.pojo.Day MONDAY;
public static final com.tplink.test.pojo.Day TUESDAY;
public static final com.tplink.test.pojo.Day WEDNESDAY;
public static final com.tplink.test.pojo.Day THURSDAY;
public static final com.tplink.test.pojo.Day FRIDAY;
public static final com.tplink.test.pojo.Day SATURDAY;
public static final com.tplink.test.pojo.Day SUNDAY;
public static com.tplink.test.pojo.Day[] values(); // 编译器添加的方法
public static com.tplink.test.pojo.Day valueOf(java.lang.String); // 编译器添加的方法,根据名字查找对象
public int getVal(); // 自定义getter
public java.lang.String getDay(); // 自定义getter
static {};
}
复制代码
默认的转换
默认的枚举类型转换只能传枚举类型的ordinal和name。
例如:
// restcontroller
@PostMapping("/day1")
public void day1(@RequestBody XxVo vo) {
...
}
// VO
@Data
public class XxVo {
private Day1 day1; // day1是上文定义的枚举类
}
复制代码
可以接收:
// ordinal
{
"day1": 0
}
// name
{
"day1": "MONDAY"
}
复制代码
不能接收:
{
"day1": "Monday"
}
复制代码
下面介绍自定义转换方法。
RequestBody中的枚举类型转换
RequestBody的解析依赖于HttpMessageConverter。
使用Jackson的@JsonValue
和@JsonCreator
注解。
@Getter
public enum Day {
MONDAY(1, "monday"),
TUESDAY(2, "tuesday"),
WEDNESDAY(3, "wednesday"),
THURSDAY(4, "thursday"),
FRIDAY(5, "friday"),
SATURDAY(6, "saturday"),
SUNDAY(-1, "sunday");
private Integer value;
private String day;
Day(int value, String day) {
this.value = value;
this.day = day;
}
@JsonValue
public Integer getValue() {
return this.value;
}
@JsonCreator
public static Day Day(Integer value) {
for (Day day : values()) {
if (day.value.equals(value)) {
return day;
}
}
return null;
}
}
复制代码
RequestParam中的枚举类型转换
RequestParam中的参数转换依赖于WebDataBinder机制。
定义一个BaseEnum
接口,自定义Converter并注册进WebMvcConfigurer。
public interface BaseEnum {
/**
* 序列化
* @return
*/
Object toValue();
/**
* 反序列化
* @param enumType 实际枚举类型
* @param value 当前值
* @param <T> 枚举类型并实现当前接口
* @return 枚举常量
*/
static <T extends Enum<T> & BaseEnum> T valueOf(Class<T> enumType, Object value) {
if (enumType == null || value == null) {
return null;
}
T[] enumConstants = enumType.getEnumConstants();
for (T enumConstant : enumConstants) {
Object enumValue = enumConstant.toValue();
if (Objects.equals(enumValue, value)
|| Objects.equals(enumValue.toString(), value.toString())) {
return enumConstant;
}
}
return null;
}
}
复制代码
@SuppressWarnings({"unchecked", "rawtypes"})
public class StringToEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnum(targetType);
}
private class StringToEnum<T extends Enum<T> & BaseEnum> implements Converter<String, T> {
private final Class<T> enumType;
public StringToEnum(Class<T> enumType) {
this.enumType = enumType;
}
@Override
public T convert(String source) {
if (source.isEmpty()) {
return null;
}
return (T) BaseEnum.valueOf(this.enumType, source.trim());
}
}
}
复制代码
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new StringToEnumConverterFactory());
}
}
复制代码
枚举类型序列化
使用Jackson的@JsonFormat
注解,不能和@JsonValue
同时使用。
@Getter
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Day {
MONDAY(0, "monday"),
TUESDAY(1, "tuesday"),
WEDNESDAY(2, "wednesday"),
THURSDAY(3, "thursday"),
FRIDAY(4, "friday"),
SATURDAY(5, "saturday"),
SUNDAY(6, "sunday");
private int val;
private String day;
Day(int val, String day) {
this.val = val;
this.day = day;
}
}
复制代码
则可序列化如下的形式:
{
"val": 0,
"day": "monday"
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END