文字列の列挙を作成する最良の方法?


364

enumタイプが文字列のセットを表すようにする最良の方法は何ですか?

私はこれを試しました:

enum Strings{
   STRING_ONE("ONE"), STRING_TWO("TWO")
}

次に、それらをどのように使用できStringsますか?

回答:


605

あなたが何をしたいのかわかりませんが、これが実際にサンプルコードを翻訳した方法です...

package test;

/**
 * @author The Elite Gentleman
 *
 */
public enum Strings {
    STRING_ONE("ONE"),
    STRING_TWO("TWO")
    ;

    private final String text;

    /**
     * @param text
     */
    Strings(final String text) {
        this.text = text;
    }

    /* (non-Javadoc)
     * @see java.lang.Enum#toString()
     */
    @Override
    public String toString() {
        return text;
    }
}

または、のゲッターメソッドを作成できますtext

あなたは今できる Strings.STRING_ONE.toString();


3
コンパイラの要件かどうかはわかりませんが、private String text最終的なものでなければなりません。
ジョナサン

7
@TomásNarrosはい、最終的に宣言するときに値を指定しない限り、コンストラクターでそれに割り当てることができます。
ジョナサン

28
@The Elite Gentleman enum定数の値が実行時に変更された場合は悪いことになるため、必要でない場合でも、それfinalが最善です。
ジョナサン

8
列挙型を用いて構築することができないことを忘れてはいけないnewコンストラクタがあるとしてprivate。基本的に、オブジェクトの作成は禁止されておりfinal、この場合は必要ありません。
Buhake Sindi 2013

6
@BuhakeSindi:それは本当ですが、偶然にsetText(String)列挙型にaを付ける傾向があり、それが地獄を解き放つ可能性がfinalあります:) 一種のドキュメントは、コンパイラサポートのある定数であることを意図しています。String定数を使用する場合public static String、それをとして宣言しませんか?
TWiStErRob 2014年

104

列挙型のカスタム文字列値

http://javahowto.blogspot.com/2006/10/custom-string-values-for-enum.htmlから

java enumのデフォルトの文字列値は、そのフェース値または要素名です。ただし、toString()メソッドをオーバーライドすることで文字列値をカスタマイズできます。例えば、

public enum MyType {
  ONE {
      public String toString() {
          return "this is one";
      }
  },

  TWO {
      public String toString() {
          return "this is two";
      }
  }
}

次のテストコードを実行すると、これが生成されます。

public class EnumTest {
  public static void main(String[] args) {
      System.out.println(MyType.ONE);
      System.out.println(MyType.TWO);
  }
}


this is one
this is two

16
これは、これを行う効率的な方法ではありません。これにより、列挙のすべての値に対して新しいカスタムクラスが作成されます。上記の例では、次のように表示されますbinEnumTest $ MyType.class EnumTest $がMyType $ 1.class EnumTest $がMyType $ 2.classまで追加されます:ディレクトリ本当迅速に。enumコンストラクターに値を渡すことにより、期待される答えとしてそれを行うのが最善です。私は実際にオーバーライドすることに同意しtoString()ません。enumの別のユーザーがgetKey()オーバーライドtoString()を予期しない可能性があるため、明示的なゲッターを使用する方が良いと思います。
Matt Quigley

@MattQuigleyに完全に同意します。そうすることで、ユーザーにtoStringを使用してはいけないものに使用するように促します。ラベルが必要な場合は、ラベル属性を追加することをお勧めします
Sebastien Lorber 2014年

また、ある時点でおそらく必要になるであろう(文字列からenumオブジェクトへ)逆の方法はありません。
エイドリアン・スミス

toStringをオーバーライドしてもvalueOf()には影響しませんか?
Dmitriusan

69

そのname()方法を使用してください:

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.ONE.name());
    }
}

enum Strings {
    ONE, TWO, THREE
}

利回りONE


17
ええ、でもStrings.STRING_ONE.name()"ONE"ではなく "STRING_ONE"になります。これは単に良い答えではありません。あなたはなど、有効なJava識別子ではありません任意の文字列を持つことはできません
マーク・ピーターズ

2
@マーク、本当、それはどんな文字も扱うことができません。OPが単一の文字を必要とする場合、この解決策はThe Elite Gentlemanの提案よりも簡単です。しかし、確かに:文字の範囲が有効なJava識別子が持つことができる文字数を超える場合、これは問題ありません。いい視点ね。
Bart Kiers、2010

toString()で表示したいもの(特にユーザーが出力を表示する場合)とは異なる列挙型の内部命名規則を持つことは非常に合理的であるため、これがOPの内容とまったく異なると思います探している。
Michael McGowan、

17
からの結果はname()、難読化プログラムによって影響を受ける可能性があります。私は少し前に同様の問題に遭遇しました。たとえば、Proguardではこれを回避する必要があります。列挙型クラスの処理
noisecapellaを

これは素晴らしいです。var_name、var_superlong_but_not_toooooo_long_nameなどの値でも機能します(三重ドットなし)

18

列挙名を必要な文字列と同じに設定するか、より一般的には、任意の属性を列挙値に関連付けることができます。

enum Strings {
   STRING_ONE("ONE"), STRING_TWO("TWO");
   private final String stringValue;
   Strings(final String s) { stringValue = s; }
   public String toString() { return stringValue; }
   // further methods, attributes, etc.
}

上部に定数、下部にメソッド/属性を配置することが重要です。


また、プライベートコンストラクターも必要です。
Buhake Sindi、

1
列挙型コンストラクタはデフォルトでプライベートであり、アクセス修飾子を必要としません。しかし、これは一般的にアクセス修飾子についての良い点です。属性とアクセサーに追加するようにコードを更新しました。
エイドリアン・スミス

15

「文字列として使用する」の意味によっては、ここで列挙型を使用したくない場合があります。ほとんどの場合、エリート紳士によって提案された解決策は、あなたが例えば自分のtoStringメソッドを、介してそれらを使用できるようになりますSystem.out.println(STRING_ONE)String s = "Hello "+STRING_TWO、しかし、あなたが本当に(例えば文字列を必要とするときSTRING_ONE.toLowerCase())、あなたは定数としてそれらを定義することを好むかもしれません。

public interface Strings{
  public static final String STRING_ONE = "ONE";
  public static final String STRING_TWO = "TWO";      
}

5
これは私が避けようとしていることです...!
ドリ

実際に、彼らもtoLowerCase()私の解決策を望んでいるなら、彼らは行くことができますStrings.STRING_TWO.toString().toLowerCase()
ブハケシンディ

確かに、それは私が解釈したようにそれらを文字列として使用していません。Rrackhamはその使用を要求していないようなので、もちろん提案された列挙型ソリューションを使用する必要があります。
hd42

6
コンストラクタinterfaceを持つfinalクラスの代わりに使用すべきではありませんprivate。それは落胆した習慣です。
Aleks N. 2014

1
@mils、列挙型を使用したソリューションはスイッチでも同様に機能します。この解決策は、文字列が直接必要な場合にのみお勧めします。
hd42

8

あなたは文字列Enumにそれを使うことができます

public enum EnumTest {
    NAME_ONE("Name 1"),
    NAME_TWO("Name 2");

    private final String name;

    /**
     * @param name
     */
    private EnumTest(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

そしてメインメソッドから呼び出す

public class Test {
    public static void main (String args[]){
        System.out.println(EnumTest.NAME_ONE.getName());
        System.out.println(EnumTest.NAME_TWO.getName());
    }
}

5

あなたがいる場合はありません使用するコンストラクタを、あなたが持っているしたい特別な名前をメソッドのために、それにこれを試してみてください。

public enum MyType {
  ONE {
      public String getDescription() {
          return "this is one";
      }
  },    
  TWO {
      public String getDescription() {
          return "this is two";
      }
  };

  public abstract String getDescription();
}

これが最も速い解決策だと思います。変数finalを使用する必要はありません。


ただし、これでもgetDescription()を呼び出す必要があります。この場合、要求者はONEを呼び出すか、定数としてアクセスします。
kinsley kajiva 2017

私はこれが好きです。より多くの情報を受け入れる必要がある場合はどうなりますか?このソリューションでは、保護された抽象メソッドを追加してオーバーライドするだけです。さらに、toString()メソッドをオーバーライドする必要はありません。そのクリーンでベストアンサーとして受け入れることができます。
Arundev

0

デフォルト値を取得および設定します。

public enum Status {

    STATUS_A("Status A"),  STATUS_B("Status B"),

    private String status;

    Status(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.