Comment convertir la valeur enum en int?

240

J'ai une fonction qui retourne un type int. Cependant, je n'ai qu'une valeur de l'énumération TAXE.

Comment puis-je convertir la valeur d'énumération TAX en un entier?

public enum TAX {
    NOTAX(0),SALESTAX(10),IMPORTEDTAX(5);

    private int value;
    private TAX(int value){
        this.value = value;
    }
}

TAX var = TAX.NOTAX; // This value will differ

public int getTaxValue()
{
  // what do do here?
  // return (int)var;
}
vrbilgi
la source
1
Copie

Réponses:

354

Vous devriez faire en sorte que l'énumération soit valueexposée, par exemple

public enum Tax {
    NONE(0), SALES(10), IMPORT(5);

    private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

...

public int getTaxValue() {
    Tax tax = Tax.NONE; // Or whatever
    return tax.getValue();
}

(J'ai changé les noms pour qu'ils soient un peu plus conventionnels et lisibles, btw.)

Cela suppose que vous souhaitiez la valeur affectée dans le constructeur. Si ce n'est pas ce que vous voulez, vous devrez nous donner plus d'informations.

Jon Skeet
la source
1
@likejiujitsu: Cela va dans la direction opposée. Dans cette question, l'OP déjà a une valeur de type Tax, et veut obtenir la valeur numérique de celui - ci.
Jon Skeet
Je viens de l'essayer et je me rends compte qu'il échoue myEnumValue = MyEnum.valueOf(myInt);l'argument doit être de type String - ou y a-t-il quelque chose qui me manque?
likejudo
Cette solution est pire que rien. Il semble que les énumérations en Java ne devraient tout simplement pas être utilisées? Ou JDK 1.8 a-t-il changé cela?
ebyrob
@ebyrob: Compte tenu du vote, il semble que beaucoup de gens soient en désaccord avec vous, comme moi. Si vous voulez un ensemble fixe de valeurs, les énumérations sont tout à fait correctes.
Jon Skeet
209

Je préfère ça:

public enum Color {

   White,

   Green,

   Blue,

   Purple,

   Orange,

   Red
}

puis:

//cast enum to int
int color = Color.Blue.ordinal();
vivia
la source
34
Ceci est incorrect / non recommandé par Joshua Bloch dans son livre Effective Java (2nd ed). Voir l'article 31.
user504342
43
@ user504342 Je n'ai pas la 2e édition du livre, pouvez-vous s'il vous plaît nous expliquer pourquoi elle n'est pas recommandée?
likejudo
17
2 raisons: premièrement, toute association entre les valeurs ordinales et les constantes se rompra si de nouvelles constantes sont ajoutées, et deux les documents de l'API le déconseillent spécifiquement.
jordanpg
8
Tellement propre et parfait. Je vois quelques "ne le fais pas" et "non recommandé". Je vais devoir chercher pourquoi c'est considéré comme mauvais. Certains des échantillons gonflés semblent mauvais OMI. Tant de travail pour accomplir une tâche aussi simple.
Herb Meehan
4
Dans une équipe, vous êtes à peu près sûr que votre co-développeur ajoutera une valeur au milieu (pire au début), ou simplement les triera parce qu'ils n'ont rien à faire et gâcher complètement le code en utilisant.ordinal()
Michael Laffargue
18

Si vous souhaitez que la valeur que vous affectez dans le constructeur, vous devez ajouter une méthode dans la définition d'énumération pour renvoyer cette valeur.

Si vous voulez un nombre unique qui représente la valeur d'énumération, vous pouvez utiliser ordinal().

unholysampler
la source
2
Faites attention. Il existe beaucoup plus d'anti-schémas de développement qui dépendent ordinal()que de cas d'utilisation valides pour ordinal(). Si vous devez stocker une valeur unique pour le enum, stockez simplement le enum. Il existe des EnumSets, des listes d'énumérations, des EnumMaps et presque toutes les autres collections d'Enum dont vous pourriez avoir besoin.
Edwin Buck
1
@EdwinBuck: C'est bon de le souligner, je voulais juste mentionner l'existence de ordinal()parce que l'OP n'a pas précisé ce qu'il voulait que l'int. Soit réellement.
unholysampler
Ne devenez pas ordinale. Veuillez vérifier l'api enum à ce sujet. Vote positif supprimé.
Aéroglisseur plein d'anguilles,
3
Je me demande ce que les gens pensent de l'utilisation de l' ordinal()intérieur au sein de l'énum lui-même. Par exemple, dire que j'ai un ENUM appelé « Season» qui contient les valeurs Spring, Summer, Autumnet Winter, et il a une méthode publique appelée next()qui retourne values()[(ordinal() + 1) % 4] Extérieurement, aucun code ne voit jamais le nombre ordinal, et il n'y aura jamais d' autres membres dans cette ENUM, cela semble donc être un cas d'utilisation valide.
Darrel Hoffman
1
@DarrelHoffman Mon sentiment est que cela est très bien, car les seuls arguments forts que je vois contre l'utilisation de ordinal()charnière sur du code lointain sont brisés par des modifications des constantes d'énumération d'énumération. Si vous souhaitez modifier les constantes de l'énumération, vous devez déjà être dans ce fichier. La plupart des énumérations sont assez courtes, et si ce n'est pas le cas, vous devriez quand même vérifier le fichier de manière plus approfondie. Dans les deux cas, vous devriez probablement avoir un test unitaire couvrant votre next()méthode de toute façon.
Alan Hensley
12

Parfois, une approche C # facilite la vie dans le monde Java ..:

class XLINK {
static final short PAYLOAD = 102, ACK = 103, PAYLOAD_AND_ACK = 104;
}
//Now is trivial to use it like a C# enum:
int rcv = XLINK.ACK;
Vladi
la source
Pour moi, c'est la voie la plus souhaitable. J'obtiens les avantages de l'énum (clarté du code), un type de données qui est compatible avec les bases de données, et je n'ai pas à rechercher 100 alternatives enum pour le faire de la "manière android". Simple et efficace.
John Ward
Agréable. C'est comme si l'énumération java était juste complètement déconnectée de la réalité de l'utilisation de l'énumération ... surtout si les gens commencent à en abuser pour des choses comme les singletons. Cette approche présente l'inconvénient de ne pas permettre de récupérer facilement toutes les valeurs.
Nyerguds
Cela n'a-t-il pas l'inconvénient d'essayer de passer une valeur d'énumération à une méthode? Vous ne pouvez plus passer un XLINK à une méthode, car il ne représente rien de concret. Vous perdez la saisie dans votre méthode. La signature de la méthode devrait être courte au lieu de XLINK.
Dustin Jensen
2

Il est peut-être préférable d'utiliser une représentation String plutôt qu'un entier, car la String est toujours valide si des valeurs sont ajoutées à l'énumération. Vous pouvez utiliser la méthode name () de l'énumération pour convertir la valeur d'énumération en chaîne et la méthode valueOf () de l'énumération pour recréer une représentation d'énumération à partir de la chaîne. L'exemple suivant montre comment convertir la valeur d'énumération en chaîne et retour (ValueType est une énumération):

ValueType expected = ValueType.FLOAT;
String value = expected.name();

System.out.println("Name value: " + value);

ValueType actual = ValueType.valueOf(value);

if(expected.equals(actual)) System.out.println("Values are equal");
Mike
la source
1
public enum Tax {

NONE(1), SALES(2), IMPORT(3);

private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public String toString() {
        return Integer.toString(value);
    }
}

class Test {
    System.out.println(Tax.NONE);    //Just an example.
}
Ieshaan Saxena
la source
0

Une approche quelque peu différente (au moins sur Android) consiste à utiliser l' annotation IntDef pour combiner un ensemble de constantes int

@IntDef({NOTAX, SALESTAX, IMPORTEDTAX})
@interface TAX {}
int NOTAX = 0;
int SALESTAX = 10;
int IMPORTEDTAX = 5;

Utiliser comme paramètre de fonction:

void computeTax(@TAX int taxPercentage){...} 

ou dans une déclaration de variable:

@TAX int currentTax = IMPORTEDTAX;
mir
la source