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:
我一直无法确定如何实现getInstance()。一旦知道要实例化的确切Enum类,就很容易:
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
.)
但是如何用一个未知的类完成上述这一行呢? (但是,已知someEnumClass是Enum的子类。)
Thanks!
谢谢!
4 个解决方案
#1
39
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");
#2
1
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:
我们想要获取Method对象,该对象反映传入的Class的valueOf方法,该方法接受String参数;然后调用它没有对象(因为它是静态的)和提供的String参数:
type.getDeclaredMethod("valueOf", String.class).invoke(null, value);
You will need to catch a boatload of different types of exceptions.
您将需要捕获大量不同类型的异常。
#3
1
So here is the code being using Spring validation and works great for me. Full code given below.
所以这里是使用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 {};
}
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;
#4
0
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 :)
但是,将字符串插入多个枚举中以寻找合适的内容会影响使用枚举的类型安全性。如果你将“红色”映射到MyColor.RED和NuclearThreatWarningLevel.RED,那么你可能至少会得到错误的类。在最坏的情况下,你可能会在你的地下掩体中停留6个月等待空气清除,当你想要的只是一辆漆成红色的车:)
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.
如果可能的话,最好重新设计代码的这个区域,这样你就不必动态地将字符串转换为几个类之一的实例。如果你扩展你的答案以包括你试图解决的问题,也许SO社区会有一些想法。
#1
39
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");
#2
1
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:
我们想要获取Method对象,该对象反映传入的Class的valueOf方法,该方法接受String参数;然后调用它没有对象(因为它是静态的)和提供的String参数:
type.getDeclaredMethod("valueOf", String.class).invoke(null, value);
You will need to catch a boatload of different types of exceptions.
您将需要捕获大量不同类型的异常。
#3
1
So here is the code being using Spring validation and works great for me. Full code given below.
所以这里是使用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 {};
}
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;
#4
0
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 :)
但是,将字符串插入多个枚举中以寻找合适的内容会影响使用枚举的类型安全性。如果你将“红色”映射到MyColor.RED和NuclearThreatWarningLevel.RED,那么你可能至少会得到错误的类。在最坏的情况下,你可能会在你的地下掩体中停留6个月等待空气清除,当你想要的只是一辆漆成红色的车:)
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.
如果可能的话,最好重新设计代码的这个区域,这样你就不必动态地将字符串转换为几个类之一的实例。如果你扩展你的答案以包括你试图解决的问题,也许SO社区会有一些想法。