10

以下のような列挙型がありますが、eclipseは、反対側の各ペアの最初の定義にエラーがあると言っています。

public enum Baz{
  yin(yang),    //Cannot reference a field before it is defined
  yang(yin),
  good(evil),   //Cannot reference a field before it is defined
  evil(good);

  public final Baz opposite;

  Baz(Baz opposite){
    this.opposite = opposite;
  }
}

私が達成したいのは、の反対のオブジェクトBaz.something.oppositeを取得するために使用できることです。これに対する可能な回避策はありますか?たぶん、以前の空のプレースホルダーであり、この例で定義されていますか?Baz.somethingyangbadyingood

4

8 に答える 8

14

switchステートメントの場合:

public enum Baz{
  yin,
  yang,
  good,
  evil;

  public Baz getOpposite() {
    switch (this) {
        case yin: return yang;
        case yang: return yin;
        case good: return evil;
        case evil: return good;
    }
    throw new AssertionError();
}

または遅延初期化:

public enum Baz{
  yin,
  yang,
  good,
  evil;

  public Baz opposite;

  static {
    yin.opposite = yang;
    yang.opposite = yin;
    good.opposite = evil;
    evil.opposite = good;
  }
}

可変フィールドをプライベートにして、ゲッターを提供することをお勧めします。

于 2012-09-25T23:20:45.230 に答える
12

次のようなことを試すことができます:

public enum Baz{
  yin("yang"),    
  yang("yin"),
  good("evil"),   
  evil("good");

  private String opposite;

  Baz(String opposite){
    this.opposite = opposite;
  }

  public Baz getOpposite(){
     return Baz.valueOf(opposite);
  }
}

そしてそれを次のように参照します

Baz.something.getOpposite()

それは、文字列表現によって列挙値を検索することによって、あなたがやろうとしていることを達成するはずです。Bazへの再帰的な参照でそれを機能させることはできないと思います。

于 2012-09-25T23:05:05.113 に答える
4

EnumMapはどうですか?

public enum Baz {
  yin,
  yang,
  good,
  evil;
  private static final Map<Baz, Baz> opposites = new EnumMap<Baz, Baz>(Baz.class);

  static {
    opposites.put(yin, yang);
    opposites.put(yang, yin);
    opposites.put(good, evil);
    opposites.put(evil, good);
  }

  public Baz getOpposite() {
    return opposites.get(this);
  }
}
于 2012-09-25T23:26:41.403 に答える
2

抽象的方法を使用して遅延させることもできます。これには、受け入れられた回答よりも型安全性の利点があります。

public enum Baz {

    yin(new OppositeHolder() {
        @Override
        protected Baz getOpposite() {
            return yang;
        }
    }),
    yang(new OppositeHolder() {
        @Override
        protected Baz getOpposite() {
            return yin;
        }
    }),
    good(new OppositeHolder() {
        @Override
        protected Baz getOpposite() {
            return evil;
        }
    }),
    evil(new OppositeHolder() {
        @Override
        protected Baz getOpposite() {
            return good;
        }
    });

    private final OppositeHolder oppositeHolder;

    private Baz(OppositeHolder oppositeHolder) {
        this.oppositeHolder = oppositeHolder;
    }

    protected Baz getOpposite() {
        return oppositeHolder.getOpposite();
    }

    private abstract static class OppositeHolder {
        protected abstract Baz getOpposite();
    }

}

そして、コードをテストします。必要だったからです。

import org.junit.Test;
import static org.junit.Assert.fail;

public class BazTest {

    @Test
    public void doTest() {
        for (Baz baz : Baz.values()) {
            System.out.println("Baz " + baz + " has opposite: " + baz.getOpposite());
            if (baz.getOpposite() == null) {
                fail("Opposite is null");
            }
        }
    }
}
于 2015-03-22T20:01:54.813 に答える
1

もう1つの選択肢:)マップを使用します。非常に冗長ですが、この方法では、各ペアを1回だけ定義でき、他の方向が推測されます。

enum Baz {

    YIN, YANG, GOOD, EVIL;

    private static final Map<Baz, Baz> opposites = new EnumMap<>(Baz.class);

    static {
        opposites.put(YIN, YANG);
        opposites.put(GOOD, EVIL);

        for (Entry<Baz, Baz> entry : opposites.entrySet()) {
            opposites.put(entry.getValue(), entry.getKey());
        }
    }

    public Baz opposite() {
        return opposites.get(this);
    }
}

個人的には、メリトンの2番目の例が一番好きです。

于 2012-09-25T23:28:58.040 に答える
0

そして、さらに別の可能な実装(他のいくつかのソリューションと同様ですが、HashMapを使用します)。

import java.util.Map;
import java.util.HashMap;

public enum Baz {
 yin,
 yang,
 good,
 evil;

 private static Map<Baz, Baz> opposites = new HashMap<Baz, Baz>();
 static {
    opposites.put(yin, yang);
    opposites.put(yang, yin);
    opposites.put(good, evil);
    opposites.put(evil, good);
 }


 public Baz getOpposite() {
  return  opposites.get(this);
 }

}
于 2012-09-25T23:25:00.630 に答える
0

そして、完全にOTTソリューションがあります。

public enum Baz {
  yin,
  yang,
  good,
  evil,
  right,
  wrong,
  black,
  white;

  private static class AutoReversingMap<K extends Enum<K>> extends EnumMap<K, K> {
    public AutoReversingMap(Class<K> keys) {
      super(keys);
    }

    // Make put do both the forward and the reverse.
    public K put(K key, K value) {
      super.put(key, value);
      super.put(value, key);
      // Better to return null here than a misleading real return of one of the supers.
      return null;
    }
  }
  private static final Map<Baz, Baz> opposites = new AutoReversingMap<Baz>(Baz.class);

  static {
    // Assume even and odd ones are opposites.
    for (int i = 0; i < Baz.values().length; i += 2) {
      opposites.put(Baz.values()[i], Baz.values()[i + 1]);
    }
  }

  public Baz getOpposite() {
    return opposites.get(this);
  }
}
于 2012-09-25T23:47:45.497 に答える
0

数年後、最短で最もハッキーなソリューション

public enum Baz {
    YIN, // Use uppercase for enum names!
    YANG,
    GOOD,
    EVIL;

    public Baz opposite() {
        return values()[ordinal() ^ 1];
    }
}

これは、各メンバーが反対であり、ペアで配置されているという仮定に依存しています。これは、JVMがオーバーヘッド全体を最適化することを期待して、フィールドをメソッドに置き換えます。これはデスクトップでは合理的ですが、Androidではあまり合理的ではありません。

オーバーヘッドを排除するために、ここで他の多くのソリューションと同じように静的初期化子を使用できます。

于 2014-05-20T08:47:35.330 に答える