Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique enum member values

Tags:

java

enums

My problem: I want to specify a 1 to 1 connection between two enums. basically:

enum MyEnum{

    ENUM_VALUE_1,
    ENUM_VALUE_2,
    ENUM_VALUE_3,

}

enum MyOtherEnum{

    OTHER_ENUM_VALUE_1(MyEnum.ENUM_VALUE_3),
    OTHER_ENUM_VALUE_2(MyEnum.ENUM_VALUE_1),
    OTHER_ENUM_VALUE_3,
    OTHER_ENUM_VALUE_4(MyEnum.ENUM_VALUE_2),

    private MyEnum pair;

    MyOtherEnum(MyEnum pair){
        this.pair=pair;
    }

}

Given this code, what is the best way to make sure, that two instances of MyOtherEnum doesn't have the same MyEnum pair? I figured some solutions, but neither seem to be good. One solution is throw an exception in the constructor, but I'm not sure if that is even doable. Another solution is a special getter method, but it can be easily bypassed with simple MyOtherEnum.values() calls.

like image 787
Attila Neparáczki Avatar asked May 23 '14 14:05

Attila Neparáczki


2 Answers

It sounds like you shouldn't implement this as a runtime check. It can only fail if a developer who has control over the code did some bad changes. Detecting changes that introduce bugs is what tests are for.

Write a simple test that checks if everything is correct. The other answers already provide some good solutions to check for duplicated enums. Instead of running the application to see if the enum initialisation fails, run the test (I hope you already write and run tests anyway).

like image 167
kapex Avatar answered Oct 06 '22 00:10

kapex


I put the "why" aside and try to answer your question:

Create a static block in MyOtherEnum that performs the check:

static{
    // This set stores all the used values
    EnumSet<MyEnum> usedValues = EnumSet.noneOf(MyEnum.class);

    for(MyOtherEnum e : values()){
        // Value already present in the set?
        if(usedValues.contains(e.pair)) throw ...; // Duplicate 
        usedValues.add(e);
    }
}

But I have to agree with the comments: Instead of writing this check, you can also simply look at your code :).

like image 24
gexicide Avatar answered Oct 05 '22 22:10

gexicide