Yanıtlar:
Evet, Blah.valueOf("A")sana vereceğim Blah.A.
Vaka dahil olmak üzere adın tam eşleşme olması gerektiğini unutmayın : Blah.valueOf("a")ve Blah.valueOf("A ")her ikisi de bir IllegalArgumentException.
Statik yöntemler valueOf()ve values()derleme zamanında oluşturulur ve kaynak kodunda görünmez. Yine de Javadoc'ta ortaya çıkıyorlar; örneğin, Dialog.ModalityTypeher iki yöntemi de gösterir.
toString()Değeri kastediyorsanız , hayır, bunu söylemezdim. name()geçersiz kılmadığınız sürece enum sabitinin gerçek tanımlı adını alırsınız.
enum Blah {...}tanım kendi beyan çalışmamalıdır valuesne de valuesOf. Aslında "sınıf" üye değişkeni bildirmemiş olsanız bile "AnyTypeName.class" yazabilirsiniz. derleyici hepsini Just Work yapar. (Bu yanıt artık 3 ay sonra sizin için yararlı olmayabilir, ancak her ihtimale karşı.)
Metin numaralandırma değeriyle aynı değilse başka bir çözüm:
public enum Blah {
A("text1"),
B("text2"),
C("text3"),
D("text4");
private String text;
Blah(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
public static Blah fromString(String text) {
for (Blah b : Blah.values()) {
if (b.text.equalsIgnoreCase(text)) {
return b;
}
}
return null;
}
}
throw new IllegalArgumentException("No constant with text " + text + " found")daha iyi olurdu return null.
İşte kullandığım şık bir yardımcı program:
/**
* A common method for all enums since they can't have another base class
* @param <T> Enum type
* @param c enum type. All enums must be all caps.
* @param string case insensitive
* @return corresponding enum, or null
*/
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
if( c != null && string != null ) {
try {
return Enum.valueOf(c, string.trim().toUpperCase());
} catch(IllegalArgumentException ex) {
}
}
return null;
}
Sonra benim enum sınıfta genellikle bazı yazarak kaydetmek için bu var:
public static MyEnum fromString(String name) {
return getEnumFromString(MyEnum.class, name);
}
Numaralandırmalarınızın tamamı büyük harf değilse, Enum.valueOfsatırı değiştirin .
Çok kötü kullanamazsınız T.classiçin Enum.valueOfolarak Tsilinir.
Etkili Java Joshua Bloch'un desenini kullanın :
(kısalık için basitleştirilmiş)
enum MyEnum {
ENUM_1("A"),
ENUM_2("B");
private String name;
private static final Map<String,MyEnum> ENUM_MAP;
MyEnum (String name) {
this.name = name;
}
public String getName() {
return this.name;
}
// Build an immutable map of String name to enum pairs.
// Any Map impl can be used.
static {
Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
for (MyEnum instance : MyEnum.values()) {
map.put(instance.getName(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name);
}
}
Ayrıca bakınız:
Enum ve Map eşlemelerini kullanan Oracle Java Örneği
Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))Ayrıca toString () (yapıcıdan geçirilir) geçersiz kılmayı ve ad yerine bunu kullanmanızı öneririz, özellikle Enum serileştirilebilir verilerle ilişkiliyse, bu, kasayı vermeden kontrol etmenizi sağlar Sonar uygun.
unmodifiableMapyine de koyacaksanız , a ile başlamanın bir yararı yoktur ConcurrentHashMap. Sadece a HashMap. (Guava's varsa ImmutableMapo zaman bunu tavsiye ederim!)
ConcurrentHashMapharitanın başlatmadan sonra asla değiştirilmediği burada kullanmak için kesinlikle hiçbir neden yoktur . Bu nedenle, örneğin, JLS'deki örneğin kendisi bile bir düzenli kullanır HashMap.
Davanıza da dikkat etmelisiniz. Açıklamama izin verin: Blah.valueOf("A")işler yapmak ama Blah.valueOf("a")işe yaramayacak. Sonra tekrar Blah.valueOf("a".toUpperCase(Locale.ENGLISH))işe yarar.
düzenlemek
Changed toUpperCaseto toUpperCase(Locale.ENGLISH)based on tc. yorum ve java belgeleri
edit2
sitesinde kullanmalısınız android Locale.USgibi Sulai işaret .
Locale.US makine tarafından okunabilen giriş / çıkış kullanımını açıkça teşvik ettiğini belirtmek isterim .
İşte herhangi bir Enum için bunu yapabilen ve büyük / küçük harfe duyarlı olmayan bir yöntem.
/**
* Finds the value of the given enumeration by name, case-insensitive.
* Throws an IllegalArgumentException if no match is found.
**/
public static <T extends Enum<T>> T valueOfIgnoreCase(
Class<T> enumeration, String name) {
for (T enumValue : enumeration.getEnumConstants()) {
if (enumValue.name().equalsIgnoreCase(name)) {
return enumValue;
}
}
throw new IllegalArgumentException(String.format(
"There is no value with name '%s' in Enum %s",
name, enumeration.getName()
));
}
equalsIgnoreCasegidilecek yol. +1
Kullanmak Blah.valueOf(string)en iyisidir ancak siz de kullanabilirsiniz Enum.valueOf(Blah.class, string).
Java 8 veya sonraki sürümlerde, Akışları kullanarak :
public enum Blah
{
A("text1"),
B("text2"),
C("text3"),
D("text4");
private String text;
Blah(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
public static Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
Kendi yardımcı programınızı yazmak istemiyorsanız Google'ın guava kütüphane:
Enums.getIfPresent(Blah.class, "A")
Dahili java fonksiyonunun aksine, A'nın Blah'ta mevcut olup olmadığını ve bir istisna atmadığını kontrol edelim.
Buradaki 2 sentim: Java8 Streams + kullanarak tam bir dizeyi kontrol etmek:
public enum MyEnum {
VALUE_1("Super"),
VALUE_2("Rainbow"),
VALUE_3("Dash"),
VALUE_3("Rocks");
private final String value;
MyEnum(String value) {
this.value = value;
}
/**
* @return the Enum representation for the given string.
* @throws IllegalArgumentException if unknown string.
*/
public static MyEnum fromString(String s) throws IllegalArgumentException {
return Arrays.stream(MyEnum.values())
.filter(v -> v.value.equals(s))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
}
}
** DÜZENLE **
fromString()Bu kuralı kullanarak adlandırdığından beri işlevi yeniden adlandırdığından, Java dilinin kendisinden bazı avantajlar elde edersiniz; Örneğin:
switch, bloklar yapabilirsiniz .orElse(null)yerine .orElseThrow()sen istisna atmak kod böylece defaultfıkra - ve gerektiğinde daha yararlı bilgiler içerir. Ve daha yumuşak kullanabilmek içinv -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Optionalgelen findFirst()isterse kullanıcı karar verme olanağı sağlayacak, .orElse(null), orElseThrow()ya da her türlü ....
Buna ihtiyacınız olabilir:
public enum ObjectType {
PERSON("Person");
public String parameterName;
ObjectType(String parameterName) {
this.parameterName = parameterName;
}
public String getParameterName() {
return this.parameterName;
}
//From String method will return you the Enum for the provided input string
public static ObjectType fromString(String parameterName) {
if (parameterName != null) {
for (ObjectType objType : ObjectType.values()) {
if (parameterName.equalsIgnoreCase(objType.parameterName)) {
return objType;
}
}
}
return null;
}
}
Bir Ek Daha:
public static String fromEnumName(String parameterName) {
if (parameterName != null) {
for (DQJ objType : DQJ.values()) {
if (parameterName.equalsIgnoreCase(objType.name())) {
return objType.parameterName;
}
}
}
return null;
}
Bu size Değerli Bir Numaralandırma Adıyla Değer döndürür. Örneğin, fromEnumName öğesinde "PERSON" sağlarsanız, size Enum Değeri yani "Kişi" değerini döndürür.
Bunu name(), Enum'un örtük statik yöntemini kullanarak yapmanın başka bir yolu . name, belirtilen dizeyi denetlemek için kullanılabilen bu numaralandırmayı oluşturmak için kullanılan dizeyi tam olarak döndürür:
public enum Blah {
A, B, C, D;
public static Blah getEnum(String s){
if(A.name().equals(s)){
return A;
}else if(B.name().equals(s)){
return B;
}else if(C.name().equals(s)){
return C;
}else if (D.name().equals(s)){
return D;
}
throw new IllegalArgumentException("No Enum specified for this string");
}
}
Test yapmak:
System.out.println(Blah.getEnum("B").name());
//it will print B B
valueOfsizin için ne yapar. Bu statik yöntem ekstra bir şey sunmaz, istisna ve hepsi. Daha sonra if / else yapıları son derece tehlikelidir ... eklenen yeni enum sabiti bu yöntemin değişmeden kırılmasına neden olur.
name()statik değildir.
Guava kütüphanelerini kullanarak çözüm. GetPlanet () yöntemi büyük / küçük harfe duyarlı değildir, bu nedenle getPlanet ("MerCUrY") Planet.MERCURY öğesini döndürür.
package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;
//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
MERCURY,
VENUS,
EARTH,
MARS,
JUPITER,
SATURN,
URANUS,
NEPTUNE;
public static Planet getPlanet(String name) {
String val = StringUtils.trimToEmpty(name).toUpperCase();
Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
Önceki yanıtlara eklemek ve null'lar ve NPE ile ilgili tartışmalardan bazılarını ele almak için, yok / geçersiz vakaları ele almak için Guava Seçeneklerini kullanıyorum. Bu, URI / parametre ayrıştırma için harika çalışır.
public enum E {
A,B,C;
public static Optional<E> fromString(String s) {
try {
return Optional.of(E.valueOf(s.toUpperCase()));
} catch (IllegalArgumentException|NullPointerException e) {
return Optional.absent();
}
}
}
Farkında olmayanlar için, İsteğe Bağlı ile null değerinden kaçınmaya ilişkin daha fazla bilgi bulabilirsiniz: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional
Java 8'de statik Harita deseni daha da kolaydır ve benim tercih ettiğim yöntemdir. Enum'u Jackson ile birlikte kullanmak istiyorsanız, toString'i geçersiz kılabilir ve ad yerine bunu kullanabilirsiniz, ardından açıklama ekleyin@JsonValue
public enum MyEnum {
BAR,
BAZ;
private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
public static MyEnum fromName(String name){
return MAP.get(name);
}
}
public enum MyEnumForJson {
BAR("bar"),
BAZ("baz");
private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
private final String value;
MyEnumForJson(String value) {
this.value = value;
}
@JsonValue
@Override
public String toString() {
return value;
}
public static MyEnumForJson fromValue(String value){
return MAP.get(value);
}
}
public static MyEnum getFromValue(String value) {
MyEnum resp = null;
MyEnum nodes[] = values();
for(int i = 0; i < nodes.length; i++) {
if(nodes[i].value.equals(value)) {
resp = nodes[i];
break;
}
}
return resp;
}
O (1) yöntem, bir hashmap kullanan tasarruf kaynaklı koddan esinlenmiştir.
public enum USER {
STUDENT("jon",0),TEACHER("tom",1);
private static final Map<String, Integer> map = new HashMap<>();
static {
for (USER user : EnumSet.allOf(USER.class)) {
map.put(user.getTypeName(), user.getIndex());
}
}
public static int findIndexByTypeName(String typeName) {
return map.get(typeName);
}
private USER(String typeName,int index){
this.typeName = typeName;
this.index = index;
}
private String typeName;
private int index;
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
Enum çok yararlıdır, Enumaşağıdaki örnekte olduğu gibi farklı dillerdeki bazı alanlara açıklama eklemek için çok şey kullanıyorum :
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
Ardından, getDescription(String lang)yönteme iletilen dil koduna göre açıklamayı dinamik olarak alabilirsiniz, örneğin:
String statusDescription = Status.valueOf("ACT").getDescription("en");
java.lang.Enum Java'daki tüm numaralandırma türlerinde kullanılabilen birkaç yararlı yöntem tanımlar:
name()Herhangi bir Enum sabitinin adını almak için yöntemi kullanabilirsiniz . Enum sabitlerini yazmak için kullanılan dize değişmezi adlarıdır.values(), bir Enum türünden tüm Enum sabitlerinin bir dizisini elde etmek için yöntem kullanılabilir.valueOf()aşağıda gösterildiği gibi herhangi bir String'i Java'da Enum sabitine dönüştürmek için yöntemi kullanabilirsiniz .public class EnumDemo06 {
public static void main(String args[]) {
Gender fromString = Gender.valueOf("MALE");
System.out.println("Gender.MALE.name() : " + fromString.name());
}
private enum Gender {
MALE, FEMALE;
}
}
Output:
Gender.MALE.name() : MALE
Bu kod snippet'inde, valueOf()yöntem Enum sabiti Gender.MALE değerini döndürür ve bu çağrıda çağrı adı döndürür "MALE".
Apache'nin commons-lang kütüphanesi, bir String'i Enum türünüzle eşleştirecek statik bir org.apache.commons.lang3.EnumUtils.getEnum işlevine sahiptir . Aslında Geoffreys ile aynı cevap ama neden zaten vahşi doğada kendi kendinize rulo.
Yararlı bir yardımcı programla en yüksek puanlı cevaba ekleniyor ...
valueOf() girdisini beğenmediği durumlarda iki farklı İstisna atar.
IllegalArgumentExceptionNullPointerExeptionGereksinimleriniz, String'inizin bir enum değeriyle kesinlikle eşleşeceğine dair bir garantiniz yoksa, örneğin String verileri bir veritabanından geliyorsa ve numaralandırmanın eski sürümünü içeriyorsa, bunları işlemeniz gerekir sıklıkla...
Bu yüzden, yazdığım, geçirdiğimiz String eşleşmediğinde döndürülecek varsayılan bir Enum tanımlamamıza izin veren yeniden kullanılabilir bir yöntem.
private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
try {
return Enum.valueOf(defaultVal.getDeclaringClass() , name);
} catch (IllegalArgumentException | NullPointerException e) {
return defaultVal;
}
}
Şöyle kullanın:
public enum MYTHINGS {
THINGONE,
THINGTWO
}
public static void main(String [] asd) {
valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}
Bir switch-versiyon henüz bahsedilmediğinden ben tanıtmak (OP enum yeniden kullanarak):
private enum Blah {
A, B, C, D;
public static Blah byName(String name) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
throw new IllegalArgumentException(
"No enum constant " + Blah.class.getCanonicalName() + "." + name);
}
}
}
Bu, valueOf(String name)yönteme herhangi bir ek değer vermediğinden , yalnızca farklı bir davranışa sahip olmak istiyorsak ek bir yöntem tanımlamak mantıklıdır. Bir yükseltmek istemiyorsak IllegalArgumentExceptionuygulamayı şu şekilde değiştirebiliriz:
private enum Blah {
A, B, C, D;
public static Blah valueOfOrDefault(String name, Blah defaultValue) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
if (defaultValue == null) {
throw new NullPointerException();
}
return defaultValue;
}
}
}
Varsayılan bir değer vererek sözleşmeyi , hiçbir durumda iade Enum.valueOf(String name)edilmeyecek IllegalArgumentExceptionşekilde atmadan saklarız null. Bu nedenle, NullPointerExceptioneğer isim ise nullve olması defaulthalinde defaultValueatarız null. İşte böyle valueOfOrDefaultçalışır.
Bu yaklaşım , Java 8'den itibaren Mapbir yöntem sağlayan -Interface tasarımını benimser Map.getOrDefault(Object key, V defaultValue).
Başka bir yardımcı program ters şekilde yakalanıyor. Adından değil, Enum'u tanımlayan bir değer kullanmak.
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;
public class EnumUtil {
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose a
* public method return value of this Enum is
* equal to <code>valor</code>.<br/>
* Such method should be unique public, not final and static method
* declared in Enum.
* In case of more than one method in match those conditions
* its first one will be chosen.
*
* @param enumType
* @param value
* @return
*/
public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
String methodName = getMethodIdentifier(enumType);
return from(enumType, value, methodName);
}
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose
* public method <code>methodName</code> return is
* equal to <code>value</code>.<br/>
*
* @param enumType
* @param value
* @param methodName
* @return
*/
public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
EnumSet<E> enumSet = EnumSet.allOf(enumType);
for (E en : enumSet) {
try {
String invoke = enumType.getMethod(methodName).invoke(en).toString();
if (invoke.equals(value.toString())) {
return en;
}
} catch (Exception e) {
return null;
}
}
return null;
}
private static String getMethodIdentifier(Class<?> enumType) {
Method[] methods = enumType.getDeclaredMethods();
String name = null;
for (Method method : methods) {
int mod = method.getModifiers();
if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
name = method.getName();
break;
}
}
return name;
}
}
Misal:
public enum Foo {
ONE("eins"), TWO("zwei"), THREE("drei");
private String value;
private Foo(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
EnumUtil.from(Foo.class, "drei")geri döner Foo.THREE, çünkü getValueFoo'daki nihai değil statik yöntem değil, benzersiz genel olan "drei" ile eşleşir. Durumda Foo daha örneğin, kamu nihai değil ve statik değildir yöntemi, üzerinde daha vardır getTranslatedöner "drei", diğer bir yöntem kullanılabilir: EnumUtil.from(Foo.class, "drei", "getTranslate").
Bir uzantı oluşturun ve arayın valueOf<MyEnum>("value"). Tür geçersizse, null olur ve ele almanız gerekir
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatif olarak, çağıran valueOf<MyEnum>("value", MyEnum.FALLBACK)ve boş bir yanıttan kaçınan varsayılan bir değer ayarlayabilirsiniz . Belirli numaralandırmanızı varsayılanın otomatik olması için genişletebilirsiniz
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Veya ikisini birden istiyorsanız, ikincisini yapın:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
Komutları numaralandırmalara dizeler olarak ayrıştırmak için bu tür bir işlemi kullanmayı seviyorum. Ben normalde "bilinmeyen" olarak numaralandırma biri var, bu yüzden (null değeri yoktur) başkaları null (bu durumda duyarsız bir temelde bile) bulunamadığında döndürmek için yardımcı olur. Bu yüzden bu yaklaşımı kullanıyorum.
static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
Enum<E> unknown=null;
for (Enum<E> enumVal: enumClass.getEnumConstants()) {
if (what.compareToIgnoreCase(enumVal.name()) == 0) {
return enumVal;
}
if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
unknown=enumVal;
}
}
return unknown;
}
Enum adını almanın en hızlı yolu, uygulama başladığında bir numaralandırma metni ve değeri haritası oluşturmak ve adı almak için Blah.getEnumName () işlevini çağırmaktır:
public enum Blah {
A("text1"),
B("text2"),
C("text3"),
D("text4");
private String text;
private HashMap<String, String> map;
Blah(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
static{
createMapOfTextAndName();
}
public static void createMapOfTextAndName() {
map = new HashMap<String, String>();
for (Blah b : Blah.values()) {
map.put(b.getText(),b.name());
}
}
public static String getEnumName(String text) {
return map.get(text.toLowerCase());
}
}
Blah.valueOf("A")yöntem büyük / küçük harfe duyarlıdır ve yabancı boşlukları tolere etmez, bu nedenle aşağıda @ JoséMi tarafından önerilen alternatif çözümdür.