从 Class使用字符串值?

发布于 2024-11-25 02:33:23 字数 682 浏览 6 评论 0 原文

我发现很难用语言表达确切的问题,所以我只举一个例子。

我有两种 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 的子类。)

谢谢!

I'm finding it difficult to put the exact question into words, so I'll just give an example.

I have two Enum types:

enum Shape {
    CAT, DOG;
}

enum Color {
    BLUE, RED;
}

I have a method:

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

I would like to use the method like:

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

I've been having trouble determining exactly how to implement getInstance(). Once you know the exact Enum class that you want to instantiate, it's easy:

Color.valueOf("RED");

But how can this above line be accomplished with an unknown Class? (It is, however, known that the someEnumClass is a subclass of Enum.)

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

傲影 2024-12-02 02:33:23
 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");

which 的快捷方式

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

And the method is to be used as:

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

Then again, you can always use

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

which is a shortcut for

Enum.valueOf(Shape.class, "CAT");
沙与沫 2024-12-02 02:33:23

我们想要获取 Method 对象,该对象反映传入的 ClassvalueOf 方法,该方法接受 String > 参数;然后在没有对象(因为它是静态的)和提供的 String 参数的情况下调用它:

type.getDeclaredMethod("valueOf", String.class).invoke(null, value);

您将需要捕获大量不同类型的异常。

We want to get the Method object which reflects the valueOf method of the passed-in Class, which accepts a String parameter; then invoke it with no object (since it's static) and the supplied String parameter:

type.getDeclaredMethod("valueOf", String.class).invoke(null, value);

You will need to catch a boatload of different types of exceptions.

失去的东西太少 2024-12-02 02:33:23

所以这里是使用 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;

So here is the code being using Spring validation and works great for me.
Full code given below.

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

}

Implementation of the above class:

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

  }

}

USAGE OF THE ABOVE ANNOTATION IS VERY SIMPLE

 @JsonProperty("lead_id")
  @EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
  private String leadId;
一桥轻雨一伞开 2024-12-02 02:33:23

由于您知道要查找的类,因此您可以询问枚举是否知道您感兴趣的内容:

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 社区会有一些想法。

Since you have an idea of what class you're looking for you can just ask the enum if it knows what you're interested in:

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

However, plugging strings into multiple enums looking for a fit compromises the type safety you get with enums. If you map "red" to both MyColor.RED and NuclearThreatWarningLevel.RED then you may, at the very least, end up with the wrong class. At the worst you could end up in your underground bunker for 6 months waiting for the air to clear, when all you wanted was a car painted red :)

It would be better to redesign this area of your code if possible so you don't have to convert a string to an instance of one of several classes dynamically. If you expand your answer to include the problem you're trying to solve perhaps the SO community will have some ideas.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文