当Java枚举遇到位掩码,还能这么玩?
阅读本文大概需要 4.2 分钟。
来自:https://juejin.cn/post/6971567246774632462
String jsonStr = JSON.toJSONString(obj,
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.PrettyFormat,
SerializerFeature.WriteNullStringAsEmpty);
// JSON.toJSONString
public static String toJSONString(Object object, SerializerFeature... features);
import static
,那么连 SerializerFeature 都不用写了。// 写三个 for 循环的原因是大概率下,不同 feature 处理时机不同,所以不能在一个 for 循环内处理
for (SerializerFeature feature : features) {
if(feature.equals(SerializerFeature.WriteDateUseDateFormat)){
// solve WriteDateUseDateFormat
}
}
for (SerializerFeature feature : features) {
if(feature.equals(SerializerFeature.PrettyFormat)){
// solve PrettyFormat
}
}
for (SerializerFeature feature : features) {
if(feature.equals(SerializerFeature.WriteNullStringAsEmpty)){
// solve WriteNullStringAsEmpty
}
}
boolean writeDateUseDateFormatEnable = false;
boolean PrettyFormatEnable = false;
boolean WriteNullStringAsEmptyEnable = false;
for (SerializerFeature feature : features) {
if(feature.equals(SerializerFeature.WriteDateUseDateFormat)){
writeDateUseDateFormatEnable = true;
}
if(feature.equals(SerializerFeature.PrettyFormat)){
PrettyFormatEnable = true;
}
if(feature.equals(SerializerFeature.WriteNullStringAsEmpty)){
WriteNullStringAsEmptyEnable = true;
}
}
枚举中的序数(ordinal)
public enum Feature {
F_A, // ordinal 0
F_B, // ordinal 1
F_C, // ordinal 2
F_D, // ordinal 3
;
}
Feature._F_A_.ordinal()
Fastjson 中的妙用
SerializerFeature
的源码中有一个 **mask(掩码) **,这个 mask 的值为 1 << ordinal
枚举中的位掩码 - Mask
public enum SerializerFeature {
WriteDateUseDateFormat,
PrettyFormat,
WriteNullStringAsEmpty
...
SerializerFeature(){
mask = (1 << ordinal());
}
public final int mask;
...
}
SerializerFeature
中,WriteDateUseDateFormat, PrettyFormat, WriteNullStringAsEmpty 三个值得序数分别为 0/1/2,左移后他们对应的二进制位如下:0 0 0 1 WriteDateUseDateFormat
0 0 1 0 PrettyFormat
0 1 0 0 WriteNullStringAsEmpty
...
1 0 0 0
多个配置的处理
int features = 0;
features |= SerializerFeature.WriteDateUseDateFormat.getMask();
0 0 0 0 [input(features)]
(|) 0 0 0 1 [mask(feature mask)]
-------------
0 0 0 1 [output(new features)]
0 0 0 1
,第 0 位上变成了 1 ,代表第 1 位的枚举值(WriteDateUseDateFormat)被启用了,接着继续对 PrettyFormat 也执行位或,
features |= SerializerFeature.PrettyFormat.getMask();
0 0 0 1 [input(features)]
(|) 0 0 1 0 [mask(feature mask)]
-------------
0 0 1 1 [output(new features)]
0 0 1 1
,第 2 位 上也变成了 1,代表第 2 位的枚举值(PrettyFormat)也被启用了判断是否配置
public static boolean isEnabled(int features, SerializerFeature feature) {
return (features & feature.mask) != 0;
}
0 0 1 1 [input(features)]
(&) 0 0 1 0 [mask(PrettyFormat)]
-------------
0 0 1 0 [output(new features)]
0 0 1 1
,和 PrettyFormat 的 mask 做位与后,就可以得出 0 0 1 0
,结果不为 0 ,所以 PrettyFormat 已经被设置了完整示例
// 存储所有配置的 Feature
int features = 0;
// 每添加一个 Feature, 就拿 features 和 当前 Feature 的掩码做位或运算
features |= SerializerFeature.WriteDateUseDateFormat.getMask();
features |= SerializerFeature.PrettyFormat.getMask();
// 再通过位与运算的结果,就可以判断某个 Feature 是否配置
boolean writeDateUseDateFormatEnabled = SerializerFeature.isEnabled(features,SerializerFeature.WriteDateUseDateFormat);
boolean prettyFormatEnabled = SerializerFeature.isEnabled(features,SerializerFeature.PrettyFormat);
boolean writeNullStringAsEmpty = SerializerFeature.isEnabled(features,SerializerFeature.WriteNullStringAsEmpty);
System.out.println("writeDateUseDateFormatEnabled: "+writeDateUseDateFormatEnabled);
System.out.println("prettyFormatEnabled: "+prettyFormatEnabled);
System.out.println("writeNullStringAsEmpty: "+writeNullStringAsEmpty);
//output
writeDateUseDateFormatEnabled: true
prettyFormatEnabled: true
writeNullStringAsEmpty: false
总结
推荐阅读:
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
朕已阅