2011-07-20 130 views
20

我發現很難將確切的問題轉化爲單詞,所以我只舉一個例子。從類<?獲取枚舉實例擴展枚舉>使用字符串值?

我有兩個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的子類。)

謝謝!

回答

35
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"); 
+0

+1枚舉是專門爲你不要需要經過反射機械你自己。很好解析和發現。 –

+0

爲什麼?因爲他要求。我試圖指出他的問題的解決方案。 – chahuistle

+0

非常好,謝謝你的解決方案和詳細的解釋。 Enum.valueOf()方法完美工作! –

1

快捷我們想要獲得Method對象它反映了傳入的ClassvalueOf方法,該方法接受String參數;然後用無對象(因爲它是靜態的)和所提供的字符串參數invoke它:

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

您將需要捕捉不同類型的異常的一大堆。

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社區可能會有一些想法。

+0

請參閱我的@在chahuistle的答案。我實際上並不知道模型中存在哪些Enum類。將來,有些可能會被添加/刪除。我在字段上使用反射來確定運行時的類型。此外,這些值是作爲來自數據庫加載的字符串提供的,所以我需要靈活處理我可以處理的類/值。 –

+0

@craig,是作爲字符串存儲在數據庫中的類名?你怎麼知道實例化哪個類? – Paul

+0

類名不存儲在數據庫中。我有幾個類「A」,「B」和「C」,每個類都包含某種類型Enum的ivar。這些枚舉類型是靜態類型的,例如。 「A」有一個Color Enum,「B」有一個Shape Enum,但是我使用一個單獨的方法來分配這些Enum字段,該方法使用反射來確定(基於A,B或C的一些實例以及String值)需要使用哪種枚舉類型。 –

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; 
+2

歡迎來到StackOverflow! OP要求通過Enum類和String獲取Enum值。 – kukido