具有不可变参数的自引用枚举

dur*_*597 9 java enums self-reference

请考虑以下sscce

public enum Flippable 
  A (Z), B (Y), Y (B), Z (A);

  private final Flippable opposite;

  private Flippable(Flippable opposite) {
    this.opposite = opposite;
  }

  public Flippable flip() {
    return opposite;
  }
}
Run Code Online (Sandbox Code Playgroud)

这不会编译,因为Z并且Y还没有被声明被允许作为AB构造函数的参数.

可能的解决方案1: 硬编码方法

public enum Flippable {
  A {
    public Flippable flip() { return Z; }
  }, B {
    public Flippable flip() { return Y; }
  }, Y {
    public Flippable flip() { return B; }
  }, Z {
    public Flippable flip() { return A; }
  };
  public abstract Flippable flip();
}
Run Code Online (Sandbox Code Playgroud)

虽然功能性,但在风格上看起来相当粗糙.虽然我无法理解为什么这会成为一个真正的问题.

潜在解决方案2: 静态加载

public enum Flippable {
  A, B, Y, Z;

  private Flippable opposite;

  static {
    for(Flippable f : Flippable.values()) {
      switch(f) {
      case A:
        f.opposite = Z;
        break;
      case B:
        f.opposite = Y;
        break;
      case Y:
        f.opposite = B;
        break;
      case Z:
        f.opposite = A;
        break;
      }
    }
  }

  public Flippable flip() {
    return opposite;
  }
}
Run Code Online (Sandbox Code Playgroud)

这比第一个解决方案更加严重,因为该领域不再是最终的,并且易受反射影响.最终这是一个模糊的担忧,但暗示代码味道不好.

有没有办法做到这一点与第一个例子基本相同,但编译正确?

rob*_*ert 13

也许不像你想要的那样漂亮......

public enum Flippable {
    A, B, Z, Y;

    static {
        A.opposite = Z;
        B.opposite = Y;
        Y.opposite = B;
        Z.opposite = A;
    }

    public Flippable flip() {
        return opposite;
    }

    private Flippable opposite;

    public static void main(String[] args) {         
        for(Flippable f : Flippable.values()) {
            System.out.println(f + " flips to " + f.flip());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)