自定义枚举实现 Java

Custom enum implementation Java

我正在尝试实现某种自定义枚举 - class 其行为类似于枚举并会实现其方法。我需要传递一组值,使它们成为最终值,并执行诸如序数、valueOf、值之类的操作。 这是我的实现:

public class CustomEnum {
    private static final Map<String,CustomEnum> valuesMap = new LinkedHashMap<>();
    private static final List<CustomEnum> valuesList = new ArrayList<>(); 

    public CustomEnum(String...data) {
        for(String s : data){
            final CustomEnum customEnum = new CustomEnum(s);
            valuesMap.put(s, customEnum);
            valuesList.add(customEnum);
        }
    }

    public CustomEnum valueOf(final String data){
        if (data == null) {
            throw new NullPointerException();
        }
        final CustomEnum customEnum = valuesMap.get(data);
        if(customEnum == null){
            throw new IllegalArgumentException();
        }
        return customEnum;
    }

    public CustomEnum[] values(){
        return valuesList.toArray(new CustomEnum[valuesList.size()]);
    }

    public int ordinal(){
        return valuesList.indexOf(this);
    }

}

当我创建一个 class 的实例时,我收到 Whosebug 错误:

 CustomEnum customEnum = new CustomEnum("white");

我明白为什么会出现这个错误,但我不知道我还能如何实现这样的 class。问题是我如何改变我的实现,但仍然保持所有方法和数据结构(数组列表、映射)的工作? 如果能提供一些帮助,我将不胜感激。

你的问题是写的构造函数实际上是一个工厂。将该功能从构造函数中移出就可以了。

public static class CustomEnum {
    private static final Map<String,CustomEnum> valuesMap = new LinkedHashMap<>();
    private static final List<CustomEnum> valuesList = new ArrayList<>();
    private final String data;

    public CustomEnum(String data) {
        this.data = data;
    }

    public CustomEnum valueOf(final String data){
        if (data == null) {
            throw new NullPointerException();
        }
        final CustomEnum customEnum = valuesMap.get(data);
        if(customEnum == null){
            throw new IllegalArgumentException();
        }
        return customEnum;
    }

    public CustomEnum[] values(){
        return valuesList.toArray(new CustomEnum[valuesList.size()]);
    }

    public int ordinal(){
        return valuesList.indexOf(this);
    }

    public static void create(String...data) {
        for(String s : data){
            final CustomEnum customEnum = new CustomEnum(s);
            valuesMap.put(s, customEnum);
            valuesList.add(customEnum);
        }
    }
}

public void test(String[] args) {
    CustomEnum.create("white");
}

另一个解决方案是第二个构造函数:

public CustomEnum(String s) {
    valuesMap.put(s, this);
    valuesList.add(this);
}

您拥有的一个构造函数正在无休止地调用自身。

你的设计有问题。
public 构造函数值 static 字段。
所以每次创建 CustomEnum 时,它们的内容都会被覆盖。

所以这些集合没有不变的元素:

private static final Map<String,CustomEnum> valuesMap = new LinkedHashMap<>();
private static final List<CustomEnum> valuesList = new ArrayList<>(); 

要解决您的问题,您有两种方法。 在任何情况下,您都必须使构造函数 private 允许不变并将创建所有 CustomEnum 实例的全局构造与每个实例的创建分离:

private CustomEnum(String data) {
    this.data = data;
}

第一种方式:直接在 class 中提供常量值(就像枚举一样)。

static{
    String[] data = {....}; // constant values
    for(String s : data){
        final CustomEnum customEnum = new CustomEnum(s);
        valuesMap.put(s, customEnum);
        valuesList.add(customEnum);
    }
}

第二种方式:使字段和方法不是 static 并允许创建多个具有不同值的 CustomEnum

private final Map<String,CustomEnum> valuesMap = new LinkedHashMap<>();
private final List<CustomEnum> valuesList = new ArrayList<>(); 

public static void of(String... data) {
    for(String d : data){
        final CustomEnum customEnum = new CustomEnum(d);
        valuesMap.put(d, customEnum);
        valuesList.add(customEnum);
    }
}