Utiliser des énumérations pour les index de tableau en Java

Lors de la lecture de Java efficace, je suis tombé sur la suggestion d ' "utiliser des énumérations au lieu des constantes int". Dans un projet en cours, je fais quelque chose de similaire à celui ci-dessous:

int COL_NAME = 0;
int COL_SURNAME = 1;

table[COL_NAME] = "JONES" 

Comment devrais-je utiliser enums à la place pour y parvenir? En raison de l'interface que je suis obligé d'utiliser, je dois utiliser un int pour mon index. L'exemple ci-dessus est juste un exemple. J'utilise en fait une API qui prend un int pour les valeurs d'index.

31
demandé sur Balder 2011-03-24 13:02:23

7 réponses

L'application d'un motif utile avec un anti-motif échoue souvent ; -)

Dans votre cas, l'utilisation d'un tableau pour des données pas vraiment de type tableau pose un problème lorsque vous souhaitez remplacer les constantes int par des valeurs enum.

Propre(re) solution serait quelque chose comme un EnumMap avec le enum valeurs clés.

, vous pouvez également utiliser table[COL_NAME.ordinal()] si vous devez absolument.

Si une API vous force à passer des valeurs int mais que vous avoir le contrôle sur les valeurs réelles (c'est-à-dire que vous pouvez passer vos propres constantes), alors vous pouvez passer à l'utilisation des valeurs enum dans votre code et convertir vers/depuis enum uniquement aux endroits où votre code s'interface avec L'API. L'opération inverse de enumValue.ordinal() est EnumClass.values()[ordinal]).

48
répondu Joachim Sauer 2011-03-24 10:11:08

On dirait que vous essayez d'utiliser un EnumMap. Ceci est une carte qui enveloppe un tableau de valeurs.

enum Column {
   NAME, SURNAME
}

Map<Column, String> table = new EnumMap<Column, String>(Column.class);

table.put(Column.NAME, "JONES");

String name = table.get(Column.NAME);

Ce serait beaucoup plus simple si vous utilisiez un POJO.

classPerson {
   String name;
   String surname;
}

Person person = new Person();
person.name = "JONES";
String name = person.name;
6
répondu Peter Lawrey 2013-11-15 11:56:29

Dépend des exigences. Vous pouvez utiliser Enum.ordinal() pour convertir une énumération en int.

Notez qu'il n'est pas possible de passer une énumération directement en tant qu'index.

Modifier:

Une Autre possibilité serait d'utiliser un Map<YourEnum, String> map, puis utiliser map.get(EnumValue).

1
répondu Thomas 2011-03-24 10:04:38

Puisque vous devez utiliser cette table et ne pouvez donc pas utiliser un EnumMap, Je pense personnellement que la meilleure solution serait de rester avec ce que vous avez. Dans une énumération, les valeurs ordinales des éléments ne sont pas censées avoir une signification intrinsèque, alors que dans votre cas elles le font, puisqu'elles sont utilisées comme indices dans la table.

Le problème que vous avez n'est pas que vous n'utilisez pas d'énumérations, c'est que vous avez besoin de valeurs magiques pour extraire les données de colonne d'une table. Dans ce cas, en utilisant integer constantes est le bon outil pour le travail, sauf si vous pouvez résoudre le problème sous-jacent de cette table.

Maintenant, vous pouvez l'aborder en enveloppant la table dans votre propre classe qui y accède, et utiliser des énumérations Dans et hors de cette classe. Mais cela introduit plus de code, une autre couche d'indirection et ne résout aucun problème pour vous, sauf qu'une énumération est un peu plus facile à maintenir qu'une liste de valeurs int (grandement compensée par le fait que vous devez maintenir le wrapper que vous avez maintenant écrit).

Vous pouvez considérer ce travail si vous écrivez une API publique que d'autres personnes utiliseront, car cela évitera de les faire dépendre de certaines valeurs magiques qui pourraient changer avec le temps (couplage serré qui va casser les choses). Si vous l'êtes, alors un wrapper qui utilise un EnumMap en interne est probablement le chemin à parcourir.

Sinon, laissez-le tel quel.

1
répondu wds 2011-03-24 10:50:07

En fonction des valeurs de votre tableau, vous pouvez regarder un objet à la place. Pour des exemples si votre tableau ressemble à ceci

person[FIRST_NAME] = "Jim Bob"
person[SURNAME] = "Jones"
person[ADDRESS] = "123 ABC St"
person[CITY] = "Pleasantville"
...

Alors ce que vous voulez vraiment, c'est quelque chose comme ça

Person jimBob = new Person("Jim Bob", "Jones");
jimBob.setAddress("123 ABC St", "Pleasantville", "SC");
....

Voir Refactoring: remplacer le tableau par L'objet

1
répondu Eva 2012-08-16 09:14:08

J'ai aussi rencontré ce problème, et étant venu du monde c++, Je ne m'attendais pas à rencontrer cela.

La beauté d'enum est que peut créer une série de constantes associées avec des valeurs uniques où la valeur réelle n'est pas pertinente. Leur utilisation rend le code plus facile à lire et empêche les variables d'être définies sur des valeurs enum invalides (en particulier en Java), mais dans une situation comme celle-ci, c'est une douleur majeure. Alors que vous pourriez avoir "animaux enum {chat, oiseau, chien}" et ne se soucient pas vraiment quelle valeur le chat, L'oiseau et le chien représentent réellement, c'est tellement agréable et propre à écrire: myPets[CHAT] = "Dexter"; myPets [oiseau] = " Polly"; MyPets [chien] = "Boo-Rooh";

Dans Ma situation, j'ai fini par écrire une fonction de conversion où vous passez une valeur enum et je retourne une constante. Je déteste faire cela avec passion, mais c'est le seul moyen propre que je connaisse pour maintenir la commodité et la vérification des erreurs d'enum.

private int getPetsValue(Pets inPet) {

    int value = 0; 
    switch (inPet) {

        case CAT:    value = 0;    break;
        case BIRD:   value = 1;    break;
        case DOG:    value = 2;    break;
        default:
            assert(false);
            value = 0;
            break;
    }
    return value;
}
0
répondu Shackleford 2012-03-07 07:53:40

, Vous pouvez définir un enum avec un constructeur comme suit:

public enum ArrayIndex {
    COL_NAME(0), COL_SURNAME(1);
    private int index;

    private ArrayIndex(int index) {
    this.index = index;
    }

public int getIndex() {
    return this.index;
}
};   

Et puis utilisez-le comme ceci:

public static void main (String args[]) {
    System.out.println("index of COL_NAME is " + ArrayIndex.COL_NAME.getIndex());
}
0
répondu david-hoze 2014-11-23 22:30:10