web-dev-qa-db-fra.com

Remplacer valueof () et toString () dans Java enum

Les valeurs de mon enum sont des mots qui doivent contenir des espaces, mais les énumérations ne peuvent pas contenir d'espaces, elles sont donc regroupées. Je veux remplacer toString() pour ajouter ces espaces là où je le dis.

Je souhaite également que l'énumération fournisse l'énum correct lorsque j'utilise valueOf() sur la même chaîne que celle où j'ai ajouté les espaces.

Par exemple:

public enum RandomEnum
{
     StartHere,
     StopHere
}

Appelez toString() sur RandomEnum dont la valeur est StartHere renvoie la chaîne "Start Here". Appelez valueof() sur cette même chaîne ("Start Here") renvoie la valeur enum StartHere.

Comment puis-je faire ceci?

112
WildBamaBoy

Vous pouvez essayer ce code. Étant donné que vous ne pouvez pas remplacer la méthode valueOf, vous devez définir une méthode personnalisée (getEnum dans l'exemple de code ci-dessous) qui renvoie la valeur dont vous avez besoin et modifiez votre client pour qu'il utilise cette méthode à la place.

public enum RandomEnum {

    StartHere("Start Here"),
    StopHere("Stop Here");

    private String value;

    RandomEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return this.getValue();
    }

    public static RandomEnum getEnum(String value) {
        for(RandomEnum v : values())
            if(v.getValue().equalsIgnoreCase(value)) return v;
        throw new IllegalArgumentException();
    }
}
180
Jugal Shah

Essayez ceci, mais je ne suis pas sûr que cela fonctionnera partout :)

public enum MyEnum {
    A("Start There"),
    B("Start Here");

    MyEnum(String name) {
        try {
            Field fieldName = getClass().getSuperclass().getDeclaredField("name");
            fieldName.setAccessible(true);
            fieldName.set(this, name);
            fieldName.setAccessible(false);
        } catch (Exception e) {}
    }
}
22
Bat

Vous pouvez utiliser une carte statique dans votre enum qui mappe des chaînes avec des constantes enum. Utilisez-le dans une méthode statique 'getEnum'. Cela évite d'avoir à parcourir les énumérations chaque fois que vous voulez en obtenir un à partir de sa valeur String.

public enum RandomEnum {

    StartHere("Start Here"),
    StopHere("Stop Here");

    private final String strVal;
    private RandomEnum(String strVal) {
        this.strVal = strVal;
    }

    public static RandomEnum getEnum(String strVal) {
        if(!strValMap.containsKey(strVal)) {
            throw new IllegalArgumentException("Unknown String Value: " + strVal);
        }
        return strValMap.get(strVal);
    }

    private static final Map<String, RandomEnum> strValMap;
    static {
        final Map<String, RandomEnum> tmpMap = Maps.newHashMap();
        for(final RandomEnum en : RandomEnum.values()) {
            tmpMap.put(en.strVal, en);
        }
        strValMap = ImmutableMap.copyOf(tmpMap);
    }

    @Override
    public String toString() {
        return strVal;
    }
}

Assurez-vous simplement que l'initialisation statique de la carte a lieu en dessous de la déclaration des constantes enum.

BTW - ce type 'ImmutableMap' provient de l'API Google guava, et je le recommande sans hésiter dans des cas comme celui-ci.


EDIT - Selon les commentaires:

  1. Cette solution suppose que chaque valeur de chaîne affectée est unique et non nulle. Étant donné que le créateur de l'énumération peut contrôler cela et que la chaîne correspond à la valeur unique et non nulle, cela semble être une restriction sûre.
  2. J'ai ajouté la méthode 'toSTring ()' comme demandé dans la question
11
pedorro

Que diriez-vous d'une implémentation Java 8? (null peut être remplacé par votre énumération par défaut)

public static RandomEnum getEnum(String value) {
    List<RandomEnum> list = Arrays.asList(RandomEnum.values());
    return list.stream().filter(m -> m.value.equals(value)).findAny().orElse(null);
}

Ou vous pouvez utiliser:

...findAny().orElseThrow(NotFoundException::new);
10
lrn2prgrm

Je ne pense pas que vous allez obtenir la valeur de ("Commencez ici") au travail. Mais pour ce qui est des espaces ... essayez ce qui suit ...

static private enum RandomEnum {
    R("Start There"), 
    G("Start Here"); 
    String value;
    RandomEnum(String s) {
        value = s;
    }
}

System.out.println(RandomEnum.G.value);
System.out.println(RandomEnum.valueOf("G").value);

Start Here
Start Here
2
Java42

Vous avez toujours une option pour implémenter dans votre enum ceci:

public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name){...}
2
Andrey Lebedenko

Ce qui suit est une alternative générique de Nice à valueOf ()

public static RandomEnum getEnum(String value) {
  for (RandomEnum re : RandomEnum.values()) {
    if (re.description.compareTo(value) == 0) {
      return re;
    }
  }
  throw new IllegalArgumentException("Invalid RandomEnum value: " + value);
}
2
exception