Java 唯一枚举成员值

Java 唯一枚举成员值,java,enums,Java,Enums,我的问题:我想在两个枚举之间指定一个1对1的连接。基本上: 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_

我的问题:我想在两个枚举之间指定一个1对1的连接。基本上:

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

}
给定此代码,什么是确保
myothernum
的两个实例不具有相同的
MyEnum
对的最佳方法?我想出了一些解决办法,但似乎都不好。一种解决方案是在构造函数中抛出异常,但我不确定这是否可行。另一种解决方案是一种特殊的getter方法,但通过简单的
MyOtherEnum.values()
调用可以轻松绕过它。

我将“为什么”放在一边,尝试回答您的问题:

MyOtherEnum
中创建执行检查的静态块:

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);
    }
}
静态{
//此集合存储所有使用的值
EnumSet usedValues=EnumSet.noneOf(MyEnum.class);
对于(MyOtherEnum e:values()){
//值是否已存在于集合中?
if(usedValues.contains(e.pair))抛出…;//重复
使用价值。添加(e);
}
}
但是我必须同意这些评论:你不必写这张支票,你也可以只看你的代码:)。

这个怎么样:

public enum MyEnum {

    ENUM_VALUE_1,
    ENUM_VALUE_2,
    ENUM_VALUE_3,

}

// All enums taken.
private static final Set<MyEnum> taken = EnumSet.noneOf(MyEnum.class);

enum MyOtherEnum {

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

    private MyEnum pair;

    MyOtherEnum(MyEnum pair) {
        if (taken.contains(pair)) {
            throw new IllegalArgumentException("Cannot pair the same MyEnum with two other enums! " + this);
        }
        taken.add(pair);
        this.pair = pair;
    }

}

public void test() {
    System.out.println("Hello: " + MyOtherEnum.OTHER_ENUM_VALUE_4);
}
公共枚举MyEnum{
枚举值为1,
枚举值2,
枚举值3,
}
//所有枚举都已完成。
私有静态最终集take=EnumSet.noneOf(MyEnum.class);
肌瘤{
其他枚举值1(MyEnum.ENUM值3),
其他枚举值2(MyEnum.ENUM值1),
其他枚举值3(MyEnum.ENUM值2),
其他枚举值4(MyEnum.ENUM值2);
私有髓鞘对;
MyOtherEnum(髓鞘对){
如果(采取。包含(对)){
抛出新的IllegalArgumentException(“不能将同一个MyEnum与其他两个枚举配对!”+this);
}
采取。添加(对);
this.pair=pair;
}
}
公开无效测试(){
System.out.println(“Hello:+MyOtherEnum.OTHER_ENUM_VALUE_4”);
}

你的问题让我有点困惑。你考虑过使用吗


A可用于确保值的唯一性,如果返回false,则只需添加中使用的值。如果值已存在,则可以使用静态块测试链接:

import java.util.HashSet;
import java.util.Set;

public class EnumTrick {
  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(MyEnum.ENUM_VALUE_2), 
    OTHER_ENUM_VALUE_4(MyEnum.ENUM_VALUE_2);


    private MyEnum pair;

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

    }

    static {
      Set<MyEnum> usedEnums = new HashSet<MyEnum>();
      for(MyOtherEnum moe : MyOtherEnum.values()){
        if(! usedEnums.add(moe.pair) ){
          throw new IllegalArgumentException(moe.pair + " is already used!");
        }
      }
    }
  }

  public static void main(String [] args){
    MyOtherEnum moe = MyOtherEnum.OTHER_ENUM_VALUE_1;
  }
}
import java.util.HashSet;
导入java.util.Set;
公共类枚举技巧{
髓鞘{
枚举值1、枚举值2、枚举值3、,
}
肌瘤{
其他枚举值1(MyEnum.ENUM值3),
其他枚举值2(MyEnum.ENUM值1),
其他枚举值3(MyEnum.ENUM值2),
其他枚举值4(MyEnum.ENUM值2);
私有髓鞘对;
MyOtherEnum(髓鞘对){
this.pair=pair;
}
静止的{
Set usedEnums=new HashSet();
对于(MyOtherEnum moe:MyOtherEnum.values()){
如果(!usedEnums.add(moe.pair)){
抛出新的IllegalArgumentException(moe.pair+“已使用!”);
}
}
}
}
公共静态void main(字符串[]args){
MyOtherEnum moe=MyOtherEnum.OTHER_ENUM_值_1;
}
}
将引发异常:

Exception in thread "main" java.lang.ExceptionInInitializerError
  at EnumTrick.main(EnumTrick.java:35)
Caused by: java.lang.IllegalArgumentException: ENUM_VALUE_2 is already used!
  at EnumTrick$MyOtherEnum.<clinit>(EnumTrick.java:28)
  ... 1 more
线程“main”java.lang.ExceptionInInitializeError中的异常 位于EnumTrick.main(EnumTrick.java:35) 原因:java.lang.IllegalArgumentException:ENUM_值_2已被使用! 在EnumTrick$MyOtherEnum处。(EnumTrick.java:28) ... 还有一个
听起来您不应该将此作为运行时检查来实现。只有控制代码的开发人员做了一些不好的更改,它才会失败。检测引入bug的更改是测试的目的


编写一个简单的测试,检查一切是否正确。其他答案已经为检查重复枚举提供了一些很好的解决方案。不要运行应用程序查看枚举初始化是否失败,而是运行测试(我希望您已经编写并运行了测试)。

?为什么?请告诉我们一些背景,这看起来可疑。另请参见:
确保您正在编写源代码的最佳方法是什么,请查看它。有两个来自两个不同位置的枚举,此附件可以使我避免在一个交换机中使用200个案例。Attila,请澄清:是否要确保
myothernum
值中没有具有相同
MyEnum
属性的对?或者您想检查两个给定的MyOtherEnum实例是否共享相同的属性?这更像是一个有趣的静默,而不是一个重要的静默。它可能会让人在几年后不再头疼。你永远不知道。我想将此连接指定为一对一(或零)连接。如果在构造枚举实例后执行静态块,则这是完美的。我想是这样的,因为您的解决方案就是基于此的。@AttilaNeparáczki:通常,Java中的所有静态内容都是按照它在文件中出现的顺序初始化的。由于枚举常量在所有静态初始值设定项之前,这是可行的。从静态初始值设定项引发异常很麻烦。我明白了。我永远不会想到这个解决方案。@OldCurmudgeon因为枚举实例构造函数是从枚举类静态初始值设定项调用的,所以您的答案也会做同样的事情(尽管是间接的)。我的意思正是您提供的:D我的同事建议在构造函数中抛出异常是一种不好的做法,我也在考虑这个问题,但对我来说似乎没用。我的意思是,枚举是给定类型的一组封闭实例,它完全由程序员控制。程序员声明这些值,因此他可以正确地配置它们。他不应该保护代码不受其他交互影响。没有其他人可以向该类型添加实例。那么,为什么要在构造函数中进行额外的验证呢?@AndreiNicusan-我完全赞成让编写错误的代码变得困难。@Andrei Nicusan:这正是断言的作用所在。如果所有代码都正确的话,这些检查应该是过时的。@Holger完全同意你们的观点,我只想强调的是,进行检查的代码(即构造函数)与可能违反规则的代码(即。