Der beste Weg, um eine Reihe von Strings zu erstellen?

364

Was ist der beste Weg, um einen enumTyp eine Reihe von Zeichenfolgen darstellen zu lassen?

Ich habe es versucht:

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

Wie kann ich sie dann als verwenden Strings?

Dori
quelle

Antworten:

605

Ich weiß nicht, was Sie tun möchten, aber so habe ich Ihren Beispielcode tatsächlich übersetzt ...

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

Alternativ können Sie eine Getter-Methode für erstellen text.

Sie können jetzt tun Strings.STRING_ONE.toString();

Buhake Sindi
quelle
3
Ich weiß nicht, ob es sich um eine Compiler-Anforderung handelt, private String textsollte aber endgültig sein.
Jonathan
7
@ Tomás Narros Ja, Sie können es weiterhin im Konstruktor zuweisen, solange Sie ihm keinen Wert geben, wenn Sie ihn für endgültig erklären.
Jonathan
28
@ The Elite Gentleman Es wäre schlecht, wenn sich der Wert einer Enum-Konstante zur Laufzeit ändern finalwürde. Selbst wenn dies nicht erforderlich ist, wäre dies am besten.
Jonathan
8
Vergessen Sie nicht, dass Enums nicht so konstruiert werden können newwie der Konstruktor private. Die Objekterstellung ist grundsätzlich verboten und finalin diesem Fall nicht unbedingt erforderlich.
Buhake Sindi
6
@BuhakeSindi: Das stimmt, aber aus Versehen kann man dazu neigen, eine setText(String)auf die Aufzählung zu setzen, und das kann die Hölle entfesseln :) finalArt dokumentiert Ihre Absicht, dass es eine Konstante mit Compiler-Unterstützung ist. Wenn Sie StringKonstanten verwenden würden, würden Sie dies nicht als deklarieren public static String, oder?
TWiStErRob
104

Benutzerdefinierte Zeichenfolgenwerte für Enum

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

Der Standardzeichenfolgenwert für Java Enum ist der Nennwert oder der Elementname. Sie können den Zeichenfolgenwert jedoch anpassen, indem Sie die toString () -Methode überschreiben. Zum Beispiel,

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

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

Wenn Sie den folgenden Testcode ausführen, wird dies erzeugt:

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
Vaichidrewar
quelle
16
Dies ist kein effizienter Weg, dies zu tun. Dadurch wird für jeden Wert in der Aufzählung eine neue benutzerdefinierte Klasse erstellt. In dem obigen Beispiel wird die folgende im sehen binEnumTest $ MyType.class EnumTest $ MyType $ 1.class EnumTest $ MyType $ 2.Klasse , die summieren: Verzeichnis echte schnell. Am besten als erwartete Antwort, indem Sie Werte an den Enum-Konstruktor übergeben. Ich bin eigentlich nicht einverstanden mit dem Überschreiben toString(); Ich glaube, es ist besser, einen expliziten Getter zu verwenden, getKey()da das Überschreiben toString()von einem anderen Benutzer der Aufzählung unerwartet sein kann.
Matt Quigley
stimme voll und ganz mit @MattQuigley überein. Ermutigen Sie die Benutzer, toString für Dinge zu verwenden, für die es nicht verwendet werden sollte. Wenn Sie ein Etikett benötigen,
Sebastien Lorber
Es gibt auch keinen Weg, um umgekehrt zu werden (von einer Zeichenfolge zum Aufzählungsobjekt), was wahrscheinlich irgendwann erforderlich sein wird.
Adrian Smith
Das Überschreiben von toString wirkt sich nicht auf valueOf () aus, oder?
Dmitriusan
69

Verwenden Sie seine name()Methode:

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

enum Strings {
    ONE, TWO, THREE
}

ergibt ONE.

Bart Kiers
quelle
17
Ja, aber Strings.STRING_ONE.name()ergibt "STRING_ONE", nicht "ONE". Das ist einfach keine gute Antwort. Sie können keine Zeichenfolge haben, die keine gültige Java-Kennung usw. wäre.
Mark Peters
2
@ Mark, stimmt, es kann kein Zeichen verarbeiten. Wenn das OP nur einen einzigen Charakter haben möchte, ist diese Lösung einfacher als der Vorschlag von The Elite Gentleman. Aber in der Tat: Wenn der Zeichenbereich den Bereich überschreitet, den ein gültiger Java-Bezeichner haben kann, ist dies ein No-Go. Guter Punkt.
Bart Kiers
Es ist sehr vernünftig, eine interne Namenskonvention für eine Aufzählung zu haben, die sich von der unterscheidet, die man mit toString () anzeigen möchte (insbesondere wenn ein Benutzer die Ausgabe sieht), daher denke ich nicht, dass dies genau das war, was das OP war Auf der Suche nach.
Michael McGowan
17
Das Ergebnis von name()kann durch ein Verschleierungsprogramm beeinflusst werden. Ich bin vor einiger Zeit auf ein ähnliches Problem gestoßen. Mit Proguard müssen Sie dies beispielsweise umgehen. Siehe Verarbeiten von Aufzählungsklassen
Noisecapella
Das ist ausgezeichnet. Funktioniert mit Werten wie: var_name, var_superlong_but_not_toooooo_long_name, sogar usw. (ohne die dreifachen Punkte)
18

Stellen Sie entweder den Namen der Aufzählung so ein, dass er mit der gewünschten Zeichenfolge übereinstimmt, oder Sie können Ihren Aufzählungswerten im Allgemeinen beliebige Attribute zuordnen:

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

Es ist wichtig, dass die Konstanten oben und die Methoden / Attribute unten stehen.

Adrian Smith
quelle
Und auch einen privaten Konstrukteur zu haben .
Buhake Sindi
1
Enum-Konstruktoren sind standardmäßig privat und erfordern keinen Zugriffsmodifikator. Aber das ist ein guter Punkt bei Zugriffsmodifikatoren im Allgemeinen. Ich habe meinen Code aktualisiert, um sie dem Attribut und dem Accessor hinzuzufügen.
Adrian Smith
15

Je nachdem, was Sie unter "Verwenden Sie sie als Zeichenfolgen" verstehen, möchten Sie hier möglicherweise keine Aufzählung verwenden. In den meisten Fällen können Sie sie mit der von The Elite Gentleman vorgeschlagenen Lösung über ihre toString-Methoden verwenden, z. B. in System.out.println(STRING_ONE)oder String s = "Hello "+STRING_TWO. Wenn Sie jedoch wirklich Strings (z. B. STRING_ONE.toLowerCase()) benötigen , möchten Sie diese möglicherweise lieber als Konstanten definieren:

public interface Strings{
  public static final String STRING_ONE = "ONE";
  public static final String STRING_TWO = "TWO";      
}
hd42
quelle
5
eigentlich ist es das, was ich zu vermeiden versuche ...!
Dori
Eigentlich toLowerCase()können sie gehen , wenn sie auch meine Lösung wollen Strings.STRING_TWO.toString().toLowerCase().
Buhake Sindi
Sicher, aber das bedeutet nicht, sie als Zeichenfolgen zu verwenden, wie ich es interpretiert habe. Da Rrackham diese Verwendung nicht zu erfordern scheint, sollte er natürlich die vorgeschlagene Enum-Lösung verwenden.
HD42
6
Sie sollten nicht interfaceanstelle einer finalKlasse mit privateKonstruktor verwenden. Es ist eine entmutigte Praxis.
Aleks N.
1
@mils, die Lösungen mit Enums funktionieren in einem Switch genauso gut. Ich würde diese Lösung nur vorschlagen, wenn Strings direkt benötigt werden.
HD42
8

Sie können das für die Zeichenfolge Enum verwenden

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

Und Aufruf von der Hauptmethode

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

Wenn Sie nicht möchten , verwenden Konstrukteure , und Sie möchten ein haben spezielle Namen für die Methode, versuchen Sie es dieses:

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

  public abstract String getDescription();
}

Ich vermute, dass dies die schnellste Lösung ist. Es ist nicht erforderlich, die Variablen final zu verwenden .

Adam111p
quelle
aber mit diesem müssen Sie immer noch getDescription () aufrufen, von dem die fragende Person ONE aufrufen oder als Konstante darauf zugreifen möchte.
Kinsley Kajiva
Ich bevorzuge das. Was passiert, wenn weitere Informationen akzeptiert werden müssen? Mit dieser Lösung fügen Sie einfach geschützte abstrakte Methoden hinzu und überschreiben diese. Darüber hinaus müssen Sie die toString () -Methode nicht überschreiben. Es ist sauber und kann als beste Antwort akzeptiert werden.
Arundev
0

Abrufen und Festlegen von Standardwerten.

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