Question

J'ai le type enum ReportTypeEnum qui est transmis entre les méthodes de toutes mes classes, mais je dois ensuite le transmettre sur l'URL afin que j'utilise la méthode ordinale pour obtenir la valeur int. Une fois que je l'ai reçu dans mon autre page JSP, je dois le reconvertir en ReportTypeEnum afin de pouvoir continuer à le transmettre.

Comment convertir un ordinal en ReportTypeEnum ?

Utilisation de Java 6 SE.

Était-ce utile?

La solution

Pour convertir un ordinal en représentation de son énumération, procédez ainsi:

ReportTypeEnum value = ReportTypeEnum.values()[ordinal];

Veuillez noter les limites du tableau.

Notez que chaque appel à values ??() renvoie un tableau cloné qui pourrait avoir un impact négatif sur les performances. Vous voudrez peut-être mettre en cache le tableau s'il doit être appelé souvent.

Exemple de code sur la mise en cache de valeurs () .

Cette réponse a été modifiée pour inclure les commentaires fournis dans les commentaires

Autres conseils

C’est presque certainement une mauvaise idée . Si l'ordinal est de facto persistant (par exemple, parce que quelqu'un a marqué l'URL en signet), cela signifie que vous devez toujours conserver la commande enum à l'avenir, ce qui peut ne pas être le cas. évident pour les responsables du code le long de la ligne.

Pourquoi ne pas coder l'en-tête enum en utilisant myEnumValue.name () (et le décoder via ReportTypeEnum.valueOf (s) )?

Si je vais utiliser beaucoup values ??() :

enum Suit {
   Hearts, Diamonds, Spades, Clubs;
   public static final Suit values[] = values();
}

Pendant ce temps partout.java:

Suit suit = Suit.values[ordinal];

Faites attention aux limites de votre tableau.

Je suis d’accord avec la plupart des gens pour dire que l’utilisation de l’ordinal est probablement une mauvaise idée. En général, je résous ce problème en donnant à l'énum un constructeur privé pouvant prendre, par exemple, une valeur de base de données, puis créer une fonction statique fromDbValue similaire à celle de la réponse de Jan.

public ReportTypeEnum {
    R1(1),
    R2(2),
    R3(3),
    R4(4),
    R5(5),
    R6(6),
    R7(7),
    R8(8);

    private static Logger log = LoggerFactory.getLogger(ReportEnumType.class);  
    private static Map<Integer, ReportTypeEnum> lookup;
    private Integer dbValue;

    private ReportTypeEnum(Integer dbValue) {
        this.dbValue = dbValue;
    }


    static {
        try {
            ReportTypeEnum[] vals = ReportTypeEnum.values();
            lookup = new HashMap<Integer, ReportTypeEnum>(vals.length);

            for (ReportTypeEnum  rpt: vals)
                lookup.put(rpt.getDbValue(), rpt);
         }
         catch (Exception e) {
             // Careful, if any exception is thrown out of a static block, the class
             // won't be initialized
             log.error("Unexpected exception initializing " + ReportTypeEnum.class, e);
         }
    }

    public static ReportTypeEnum fromDbValue(Integer dbValue) {
        return lookup.get(dbValue);
    }

    public Integer getDbValue() {
        return this.dbValue;
    }

}

Vous pouvez maintenant modifier l'ordre sans modifier la recherche, et inversement.

Vous pouvez utiliser une table de recherche statique:

public enum Suit {
  spades, hearts, diamonds, clubs;

  private static final Map<Integer, Suit> lookup = new HashMap<Integer, Suit>();

  static{
    int ordinal = 0;
    for (Suit suit : EnumSet.allOf(Suit.class)) {
      lookup.put(ordinal, suit);
      ordinal+= 1;
    }
  }

  public Suit fromOrdinal(int ordinal) {
    return lookup.get(ordinal);
  }
}

C'est ce que j'utilise. Je ne prétends pas que c'est beaucoup moins "efficace" que les solutions plus simples ci-dessus. Ce qu'il fait, c'est fournir un message d'exception beaucoup plus clair que "ArrayIndexOutOfBounds". lorsqu'une valeur ordinale invalide est utilisée dans la solution ci-dessus.

Il utilise le fait que javadoc d’EnumSet spécifie que l’itérateur renvoie les éléments dans leur ordre naturel. Il y a une affirmation si ce n'est pas correct.

Le test JUnit4 montre comment il est utilisé.

 /**
 * convert ordinal to Enum
 * @param clzz may not be null
 * @param ordinal
 * @return e with e.ordinal( ) == ordinal
 * @throws IllegalArgumentException if ordinal out of range
 */
public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) {
    EnumSet<E> set = EnumSet.allOf(clzz);
    if (ordinal < set.size()) {
        Iterator<E> iter = set.iterator();
        for (int i = 0; i < ordinal; i++) {
            iter.next();
        }
        E rval = iter.next();
        assert(rval.ordinal() == ordinal);
        return rval;
    }
    throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size());
}

@Test
public void lookupTest( ) {
    java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3);
    System.out.println(tu);
}

C’est ce que je fais sur Android avec Proguard:

public enum SomeStatus {
    UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order

    private static SomeStatus[] values = null;
    public static SomeStatus fromInteger(int i) {
        if(SomeStatus.values == null) {
            SomeStatus.values = SomeStatus.values();
        }
        if (i < 0) return SomeStatus.values[0];
        if (i >= SomeStatus.values.length) return SomeStatus.values[0];
        return SomeStatus.values[i];
    }
}

c'est court et je n'ai pas besoin de m'inquiéter d'avoir une exception dans Proguard

public enum Suit implements java.io.Serializable, Comparable<Suit>{
  spades, hearts, diamonds, clubs;
  private static final Suit [] lookup  = Suit.values();
  public Suit fromOrdinal(int ordinal) {
    if(ordinal< 1 || ordinal> 3) return null;
    return lookup[value-1];
  }
}

la classe de test

public class MainTest {
    public static void main(String[] args) {
        Suit d3 = Suit.diamonds;
        Suit d3Test = Suit.fromOrdinal(2);
        if(d3.equals(d3Test)){
            System.out.println("Susses");
        }else System.out.println("Fails");
    }
}

J'apprécie que vous partagiez avec nous si vous avez un code plus efficace. Mon enum est énorme et appelé des milliers de fois.

Donc, une façon est de faire ExampleEnum valueOfOrdinal = ExampleEnum.values ??() [ordinal]; qui fonctionne et qui est simple, cependant, Comme mentionné précédemment, ExampleEnum.values ??() renvoie un nouveau tableau cloné pour chaque appel. Cela peut être inutilement coûteux. Nous pouvons résoudre ce problème en mettant en cache le tableau comme suit ExampleEnum [] values ??= values ??() . C'est aussi "dangereux" pour permettre à notre tableau en cache d'être modifié. Quelqu'un pourrait écrire ExampleEnum.values ??[0] = ExampleEnum.type2; Donc, je le rendrais privé avec une méthode d'accesseur ne faisant pas de copie supplémentaire.

private enum ExampleEnum{
    type0, type1, type2, type3;
    private static final ExampleEnum[] values = values();
    public static ExampleEnum value(int ord) {
        return values[ord];
    }
}

Vous utiliseriez ExampleEnum.value (ordinal) pour obtenir la valeur enum associée à ordinal

Vous pouvez définir une méthode simple telle que:

public enum Alphabet{
    A,B,C,D;

    public static Alphabet get(int index){
        return Alphabet.values()[index];
    }
}

Et utilisez-le comme:

System.out.println(Alphabet.get(2));

Chaque énumération a name (), ce qui donne une chaîne portant le nom du membre enum.

Étant donné enum Suit {Heart, Spade, Club, Diamant} , Suit.Heart.name () donnera Heart .

Chaque enum a une méthode valueOf () , qui prend un type enum et une chaîne pour effectuer l'opération inverse:

Enum.valueOf (Suit.class, "Heart") renvoie Suit.Heart .

Pourquoi quiconque utiliserait des ordinaux me dépasse. Cela peut prendre des nanosecondes plus rapidement, mais cela n’est pas sûr si les membres de l’énumération changent, car un autre développeur ne sait peut-être pas que du code s’appuie sur des valeurs ordinales (en particulier dans la page JSP citée dans la question). temps, sans utiliser un entier sur une chaîne).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top