web-dev-qa-db-ja.com

Java enum - なぜ名前の代わりにtoStringを使うのか

あなたがメソッドname()で列挙型APIを見るならば、それはそれを言います:

列挙型宣言で宣言されているとおりに、この列挙型定数の名前を返します。 toStringメソッドはよりユーザーフレンドリな名前を返す可能性があるため、ほとんどのプログラマはこれよりもtoStringメソッドを使用する必要があります。この方法は主に正確さが正確な名前を得ることにかかっている特別な状況での使用のために設計されており、それはリリースごとに変わりません。

toString()を使うほうがよいのはなぜですか?私はtoStringがname()が既にfinalの時に上書きされるかもしれないことを意味します。そのため、toStringを使用して誰かがそれをオーバーライドしてハードコードされた値を返すと、アプリケーション全体が停止します。また、ソースを見るとtoString()メソッドは正確に名前だけを返します。それは同じことです。

161
spauny

それは本当にあなたが戻り値で何をしたいのかに依存します。

  • 列挙型定数を宣言するために使用される正確な名前を取得する必要がある場合は、toStringがオーバーライドされている可能性があるので、name()を使用する必要があります。
  • ユーザフレンドリな方法でenum定数を表示したい場合は、上書きされた(またはされていない)可能性があるtoStringを使用してください。

混乱を招く可能性があると思われる場合は、より具体的なgetXXXメソッドを提供します。次に例を示します。

public enum Fields {
    LAST_NAME("Last Name"), FIRST_NAME("First Name");

    private final String fieldDescription;

    private Fields(String value) {
        fieldDescription = value;
    }

    public String getFieldDescription() {
        return fieldDescription;
    }
}
189
assylias

コード内で比較を行う場合、または内部使用のためにハードコードされた値を使用する場合は、name()を使用してください。

ユーザーに情報を提示したい場合はtoString()を使用してください(開発者がログを見ている場合も含みます)。特定の値を与えるtoString()にあなたのコードに頼らないでください。特定の文字列に対して絶対にテストしないでください。誰かがtoString()の戻り値を正しく変更したときにコードが壊れたとしても、それはすでに壊れています。

Javadocから(強調私のもの):

オブジェクトの文字列表現を返します。一般に、toStringメソッドはこのオブジェクトを"textually表す"という文字列を返します。結果は、簡潔でわかりやすい読みやすい人になるはずです。 すべてのサブクラスがこのメソッドをオーバーライドすることが推奨されています。

53
Denys Séguret

name()enumの「組み込み」メソッドです。それは最終的なものであり、その実装を変更することはできません。それは書かれているようにenum定数の名前を返します。大文字、スペースなしなど.

MOBILE_PHONE_NUMBERMobile phone numberを比較してください。どちらのバージョンが読みやすいですか?私は2番目を信じます。これが違いです。name()は常にMOBILE_PHONE_NUMBERを返します。toString()はオーバーライドしてMobile phone numberを返すことができます。

23
AlexR

ほとんどの人はJavadocのアドバイスに盲目的に従いますが、実際にはtoString()を避けたいという非常に特殊な状況があります。たとえば、私は自分のJavaコードで列挙型を使用していますが、データベースにシリアライズし、また戻す必要があります。 toString()を使用した場合は、他の人が指摘したように、技術的にはオーバーライドされた動作になります。

さらに、データベースからデシリアライズすることもできます。たとえば、これは常にJavaで機能するはずです。

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());

これは保証されていませんが:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());

ところで、Javadocが「ほとんどのプログラマはそうすべきだ」と明示的に言うのは非常に奇妙だと思います。私はenumのtoStringの中でごくわずかなユースケースを見つけます、人々がそれを「フレンドリーネーム」のために使っているならばそれは明らかに悪い使い方です。 name()メソッドを使用してください。

12
coding

name()は、文字列として列挙型のJavaコード内のテキスト名です。つまり、Javaコードに実際に現れる可能性のある文字列に限定されますが、望ましい文字列すべてがコードで表現できるわけではありません。たとえば、数字で始まる文字列が必要な場合があります。 name()があなたに代わってその文字列を取得することはできません。

4
Intropy

Name()とtoString()が異なることを意味する場合の実用的な例は、single-value enumを使用してシングルトンを定義するパターンです。最初は驚くほど見えますが、多くの意味があります。

enum SingletonComponent {
    INSTANCE(/*..configuration...*/);

    /* ...behavior... */

    @Override
    String toString() {
      return "SingletonComponent"; // better than default "INSTANCE"
    }
}

このような場合には:

SingletonComponent myComponent = SingletonComponent.INSTANCE;
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better
4
Marcin