自定义枚举实现Java

时间:2017-11-22 07:04:03

标签: java enums stack-overflow

我正在尝试实现某种自定义枚举 - 一个类似于枚举的类,并将实现其方法。我需要传递一组值使它们成为最终值并执行像ordinal,valueOf,values这样的操作。 这是我的实施:

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);
    }

}

当我创建一个类的实例时,我得到了StackOverflow错误:

 CustomEnum customEnum = new CustomEnum("white");

我理解为什么会发生这种错误,但我不知道我怎么能实现这样的类。问题是我如何改变我的实现,但仍然保持所有的方法和数据结构(arraylists,map)工作? 我会非常感谢你的帮助。

3 个答案:

答案 0 :(得分:2)

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

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

你拥有的一个构造函数无休止地呼唤着自己。

答案 1 :(得分:1)

你的问题是写的构造函数实际上是一个工厂。将该功能移出构造函数,您就会感觉良好。

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");
}

答案 2 :(得分:1)

你有设计问题 公共构造函数值为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;
}

第一种方法:直接在类中提供常量值(如枚举一样)。

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);
    }
}