Java特性组合的通用方案

简介: Java特性组合的通用方案


一、背景
一些框架的特性组合,以及开发中业务的某个字段是多个特征组合,如果直接用数字,组合较多保存非常复杂。

这里提供一个参考工具类, 大家感兴趣可以参考改造。

二、源码
特征

public interface Feature {

    /**
     * 获取特性(掩码)
     */
    int getMask();

    /**
     * 所有特性
     */
    Feature[] listAll();
}

特征工具类

public class FeatureUtil {
    /**
     * 此特性是否开启
     *
     * @param features 特性值
     * @param feature  某个特性
     * @return 是否开启
     */
    public static boolean isEnabled(int features, Feature feature) {
        return (features & feature.getMask()) != 0;
    }

    /**
     * 配置某个特性
     *
     * @param features 特性值
     * @param feature  某个特性
     * @param state    是否开启
     * @return
     */
    public static int config(int features, Feature feature, boolean state) {
        if (state) {
            features |= feature.getMask();
        } else {
            features &= ~feature.getMask();
        }

        return features;
    }

    /**
     * 开启某些特性的值
     *
     * @param features 特性数组
     * @return 特性值
     */
    public static int of(Feature... features) {
        if (features == null) {
            return 0;
        }
        return of(Stream.of(features).collect(Collectors.toSet()));
    }

    /**
     * 开启某些特性的值
     *
     * @param features 特性数组
     * @return 特性值
     */
    public static int of(Set<Feature> features) {
        if (features == null) {
            return 0;
        }

        int value = 0;

        for (Feature feature : features) {
            value |= feature.getMask();
        }

        return value;
    }

    /**
     * 判断特性值包含哪些特性
     *
     * @param features     特性值
     * @param featureArray 特性数组
     * @return 包含的特性
     */
    public static Set<Feature> resolve(Integer features, Feature[] featureArray) {
        if (featureArray == null) {
            throw new IllegalArgumentException("特征数组不为null");
        }
        if (features == null || features == 0) {
            return new HashSet<>(0);
        }

        Set<Feature> featureSet = new HashSet<>();
        for (Feature feature : featureArray) {
            if ((features & feature.getMask()) != 0) {
                featureSet.add(feature);
            }
        }
        return featureSet;
    }


}

枚举举例

public enum DemoEnum implements Feature {

    FIRST("第一个"),
    SECOND("第二个"),
    THIRD("第三个");


    DemoEnum() {
        mask = (1 << ordinal());
    }

     DemoEnum(String desc) {
        mask = (1 << ordinal());
        this.desc = desc;
    }

    private final int mask;


    private String desc;

    @Override
    public final int getMask() {
        return mask;
    }

    @Override
    public Feature[] listAll() {
        return DemoEnum.values();
    }

    public String getDesc() {
        return desc;
    }
}

测试类

public class FeatureUtilTest {
    private int features;

    @Before
    public void init() {
        features = FeatureUtil.of(DemoEnum.values());
    }

    @Test
    public void isEnabled() {
        boolean enabledFirst = FeatureUtil.isEnabled(features, DemoEnum.FIRST);
        boolean enabledSecond = FeatureUtil.isEnabled(features, DemoEnum.SECOND);
        Assert.assertTrue(enabledFirst);
        Assert.assertTrue(enabledSecond);
    }

    @Test
    public void config() {
        int defaultFeature = 0;
        int enableFirst = FeatureUtil.config(defaultFeature, DemoEnum.FIRST, true);
        int enableFirst2 = FeatureUtil.of(DemoEnum.FIRST);
        Assert.assertEquals(enableFirst, enableFirst2);
    }

    @Test
    public void of() {
        // 前两个特性
        int two = FeatureUtil.of(DemoEnum.FIRST, DemoEnum.SECOND);
        Assert.assertEquals(two, 3);

        // 后两个特性
        int lastTwo = FeatureUtil.of(DemoEnum.THIRD, DemoEnum.SECOND);
        Assert.assertEquals(lastTwo, 6);

    }

    @Test
    public void resolve() {
        int features = FeatureUtil.of(DemoEnum.FIRST, DemoEnum.THIRD);
        Set<Feature> resolve = FeatureUtil.resolve(features, DemoEnum.values());

        Assert.assertEquals(resolve.size(), 2);
        Assert.assertTrue(resolve.contains(DemoEnum.FIRST));
        Assert.assertTrue(resolve.contains(DemoEnum.THIRD));

    }
}

三、解析
java.lang.Enum#ordinal 函数继承自枚举对象,获取该枚举值在枚举类中的排序,第一个为0,往后依次是1,2...。

这样不同的枚举通过左移进行区分,不同的特征组合通过 不同特征之间的&运算即可区分。

如特征1 + 特征4   则,两个特征的掩码 按位或即可。

如果取消某个特性,总特性值&=~某个性,让某个特性位置为0即可。

怎么证明隐式继承了那个类呢?

方法1:单元测试

@Test
public void testExtends(){
    Assert.assertTrue(DemoEnum.FIRST instanceof Enum);
}

方法2:源码注释法

Enum类的注释第一句话就是:

This is the common base class of all Java language enumeration types.
这是Java语言中枚举类型的基类。

方法3:反解析

随手写一个枚举类

public enum SomeEnum {
}
javac SomeEnum.java

javap -verbose  SomeEnum.class

Compiled from "SomeEnum.java"
public final class com.chujianyun.common.enums.SomeEnum extends java.lang.Enum<com.chujianyun.common.enums.SomeEnum>

...
很明显可以看出继承自java.lang.Enum类。

另外我们还有意外发现,该类自动加上了final修饰符,因此无法再继承。

四、总结
由于枚举隐式继承了Enum类,由于Java不支持多ji'cheng因此如果想实现统一的方法,只能通过实现接口方式。

位运算的恰当使用可以将一些复杂逻辑简单化,可以非常容易得应对变化。

我们学习的时候,写代码的时候多去源码里看看,会有一些意外收获。

有时间研究下Java反解析class文件去读读字节码可以收获更多。

创作不易,如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。

相关文章
|
2天前
|
安全 Java UED
深度解析Java中方法内的异步调用实践与应对方案
深度解析Java中方法内的异步调用实践与应对方案
8 1
|
2天前
|
Java API 开发者
Java 8的新特性简单分享(后续有系列篇~敬请期待)
Java 8的新特性简单分享(后续有系列篇~敬请期待)
7 1
|
3天前
|
JavaScript 前端开发 Java
Java11 新特性深度解析
Java11 新特性深度解析
|
6天前
|
安全 Java
深度解读Java的继承和多态的特性
深度解读Java的继承和多态的特性
|
6天前
|
算法 Java
垃圾回收机制(Garbage Collection,GC)是Java语言的一个重要特性,它自动管理程序运行过程中不再使用的内存空间。
【6月更文挑战第24天】Java的GC自动回收不再使用的内存,关注堆中的对象。通过标记-清除、复制、压缩和分代等算法识别无用对象。GC分为Minor、Major和Full类型,针对年轻代、老年代或整个堆进行回收。性能优化涉及算法选择和参数调整。
18 3
|
12天前
|
Java 数据安全/隐私保护 开发者
Java是一种完全支持面向对象编程的语言,其面向对象特性包括封装、继承、多态和抽象等
【6月更文挑战第18天】**面向对象编程(OOP)通过对象封装状态和行为,实现问题域的抽象。Java全面支持OOP,核心特性包括**: - **封装**:保护数据安全,隐藏内部细节。 - **继承**:子类继承父类属性和行为,促进代码重用。 - **多态**:一个接口多种实现,增强灵活性和扩展性。 - **抽象**:通过接口和抽象类抽离共性,简化复杂性。 **Java的OOP便于理解和解决复杂系统问题。**
26 3
|
13天前
|
并行计算 Java API
【Java】Java18的新特性
【Java】Java18的新特性
14 3
|
16天前
|
Java 视频直播 数据库连接
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
20 2
|
16天前
|
Java
Java 8 新特性:深入理解 Lambda 表达式的强大与应用
Java 8 新特性:深入理解 Lambda 表达式的强大与应用
14 2
|
16天前
|
安全 Java API
深入解析 Java 8 新特性:LocalDate 的强大功能与实用技巧
深入解析 Java 8 新特性:LocalDate 的强大功能与实用技巧
19 1