从类<! - 获取枚举实例?扩展Enum - >使用String值?

时间:2011-07-20 21:41:28

标签: java class reflection enums instantiation

我发现很难将确切的问题写成文字,所以我只想举个例子。

我有两种Enum类型:

enum Shape {
    CAT, DOG;
}

enum Color {
    BLUE, RED;
}

我有一个方法:

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

我想使用如下方法:

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

我一直无法确定如何实施getInstance()。一旦知道要实例化的确切Enum类,就很容易:

Color.valueOf("RED");

但是如何用一个未知的Class完成上述这一行呢? (但是,已知someEnumClassEnum的子类。)

谢谢!

4 个答案:

答案 0 :(得分:43)

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

该方法用作:

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

然后,您可以随时使用

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

这是

的快捷方式
Enum.valueOf(Shape.class, "CAT");

答案 1 :(得分:1)

我们希望获得反映传入Method的{​​{1}}方法的valueOf对象,该方法接受Class参数;然后String它没有对象(因为它是静态的)和提供的String参数:

invoke

您将需要捕获大量不同类型的例外情况。

答案 2 :(得分:1)

所以这里是使用Spring验证的代码,对我来说很有用。 完整代码如下。

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 {};

}

上述课程的实施:

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());
    }

  }

}

上述注释的使用非常简单

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

答案 3 :(得分:0)

既然你已经知道你正在寻找什么课程,你可以问一下它是否知道你感兴趣的课程:

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;
  }
}

但是,将字符串插入多个枚举中以寻找合适的内容会影响使用枚举获得的类型安全性。如果您将“红色”映射到MyColor.REDNuclearThreatWarningLevel.RED,那么您可能至少会得到错误的类。最坏的情况是你可能会在地下掩体中停留6个月,等待空气清空,当你想要的只是一辆涂成红色的汽车时:)

如果可能的话,最好重新设计代码的这个区域,这样你就不必动态地将字符串转换为几个类之一的实例。如果你扩展你的答案以包括你想要解决的问题,也许SO社区会有一些想法。