into - java enum use cases




Ottieni l'istanza Enum dalla classe<? estende Enum> usando il valore String? (3)

Sto trovando difficile mettere la domanda esatta in parole, quindi darò solo un esempio.

Ho due tipi di Enum :

enum Shape {
    CAT, DOG;
}

enum Color {
    BLUE, RED;
}

Ho un metodo:

public Object getInstance(String value, Class<?> type);

Mi piacerebbe usare il metodo come:

// someValue is probably "RED", and someEnumClass is probably Color.class
Color c = getInstance(someValue, someEnumClass);

Ho avuto problemi a determinare esattamente come implementare getInstance() . Una volta che conosci l'esatta classe Enum che vuoi istanziare, è facile:

Color.valueOf("RED");

Ma come si può raggiungere questa linea sopra con una Class sconosciuta? (È noto, tuttavia, che someEnumClass è una sottoclasse di Enum .)

Grazie!


Dato che hai un'idea di quale classe stai cercando, puoi chiedere l'enum se sa a cosa ti interessa:

public enum MyColor
{
  RED  ("red", Color.RED),
  BLUE ("blue", Color.BLUE),
  TAUPE ("brownish", new COLOR(80,64,77));

  private final String _name;
  private final Color _color;

  MyColor(String name, Color color)
  {
    _name = name;
    _color = color;
  }

  public static Color parseColor(String colorName)
  {
    for (MyColor mc : MyColor.values())
    {
      if (mc._name.equalsIgnoreCase(colorName))
        return mc._color;
    }
    return null;
  }
}

Tuttavia, il collegamento di stringhe in enumerazioni multiple alla ricerca di un compromesso compromette la sicurezza del tipo che si ottiene con le enumerazioni. Se si MyColor.RED mapping "rosso" su MyColor.RED e NuclearThreatWarningLevel.RED si può, perlomeno, finire con la classe sbagliata. Nel peggiore dei casi potresti finire nel tuo bunker sotterraneo per 6 mesi in attesa che l'aria si schiarisca, quando tutto ciò che volevi era una macchina dipinta di rosso :)

Sarebbe meglio ridisegnare quest'area del codice, se possibile, in modo da non dover convertire dinamicamente una stringa in un'istanza di una delle varie classi. Se espandi la tua risposta per includere il problema che stai cercando di risolvere, forse la comunità SO avrà qualche idea.


Quindi, il codice sta usando la validazione di Spring e funziona perfettamente per me. Codice completo indicato di seguito.

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.NotNull;

@Documented
@Constraint(validatedBy = EnumValidatorImpl.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@NotNull(message = "Value cannot be null")
@ReportAsSingleViolation
public @interface EnumValidator {

  Class<? extends Enum<?>> enumClazz();

  String message() default "Value is not valid";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

}

Implementazione della classe di cui sopra:

import java.util.ArrayList;
import java.util.List;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> {

  List<String> valueList = null;

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if(!valueList.contains(value.toUpperCase())) {
      return false;
    }
    return true;
  }

  @Override
  public void initialize(EnumValidator constraintAnnotation) {
    valueList = new ArrayList<String>();
    Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClazz();

    @SuppressWarnings("rawtypes")
    Enum[] enumValArr = enumClass.getEnumConstants();

    for(@SuppressWarnings("rawtypes")
    Enum enumVal : enumValArr) {
      valueList.add(enumVal.toString());
    }

  }

}

L'UTILIZZO DELL'ANNOTIZIONE DI CUI SOPRA È MOLTO SEMPLICE

 @JsonProperty("lead_id")
  @EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
  private String leadId;

 public static <T extends Enum<T>> T getInstance(final String value, final Class<T> enumClass) {
     return Enum.valueOf(enumClass, value);
 }

E il metodo deve essere usato come:

final Shape shape = getInstance("CAT", Shape.class);

Quindi di nuovo, puoi sempre usare

final Shape shape = Shape.valueOf("CAT");

che è una scorciatoia per

Enum.valueOf(Shape.class, "CAT");






instantiation