Câu trả lời:
Vâng, Blah.valueOf("A")
sẽ cung cấp cho bạn Blah.A
.
Lưu ý rằng tên phải là một kết hợp chính xác , bao gồm cả trường hợp: Blah.valueOf("a")
và Blah.valueOf("A ")
cả hai ném một IllegalArgumentException
.
Các phương thức tĩnh valueOf()
và values()
được tạo tại thời gian biên dịch và không xuất hiện trong mã nguồn. Chúng xuất hiện trong Javadoc, mặc dù; ví dụ, Dialog.ModalityType
hiển thị cả hai phương thức
toString()
giá trị, không, tôi sẽ không nói điều đó. name()
sẽ cho bạn tên được xác định thực tế của hằng số enum trừ khi bạn ghi đè lên nó.
enum Blah {...}
Định nghĩa thực tế không nên cố gắng khai báo values
cũng không valuesOf
. Nó giống như cách bạn có thể viết "AnyTypeName. Class" mặc dù bạn chưa bao giờ thực sự khai báo biến thành viên "class"; trình biên dịch làm cho tất cả chỉ hoạt động. (Câu trả lời này có thể không còn hữu ích với bạn 3 tháng sau, nhưng chỉ trong trường hợp.)
Một giải pháp khác nếu văn bản không giống với giá trị liệt kê:
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")
sẽ là tốt hơn so với return null
.
Đây là một tiện ích tiện lợi tôi sử dụng:
/**
* 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;
}
Sau đó, trong lớp enum của tôi, tôi thường có điều này để lưu một số cách gõ:
public static MyEnum fromString(String name) {
return getEnumFromString(MyEnum.class, name);
}
Nếu enum của bạn không phải là tất cả các mũ, chỉ cần thay đổi Enum.valueOf
dòng.
Thật tệ, tôi không thể sử dụng T.class
cho Enum.valueOf
như T
bị xóa.
Sử dụng mẫu từ Joshua Bloch, Java hiệu quả :
(đơn giản hóa cho ngắn gọn)
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);
}
}
Cũng thấy:
Ví dụ Java Java sử dụng Enum và Bản đồ các thể hiện
Thứ tự thực hiện các khối tĩnh trong loại Enum
Làm cách nào tôi có thể tra cứu một enum Java từ giá trị Chuỗi của nó
Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))
Tôi cũng khuyên bạn nên ghi đè toString () (được truyền qua hàm tạo) và sử dụng tên đó thay vì tên, đặc biệt là nếu Enum được liên kết với dữ liệu tuần tự hóa vì điều này cho phép bạn kiểm soát vỏ mà không đưa ra Sonar một phù hợp.
unmodifiableMap
nào đó, thì không có lợi ích gì khi bắt đầu với a ConcurrentHashMap
. Chỉ cần sử dụng một HashMap
. (Nếu bạn có Guava ImmutableMap
thì tôi khuyên bạn nên thay thế!)
ConcurrentHashMap
ở đây, nơi bản đồ không bao giờ được sửa đổi sau khi khởi tạo. Do đó, tại sao ngay cả ví dụ trong chính JLS cũng sử dụng thông thường HashMap
.
Bạn cũng nên cẩn thận với trường hợp của bạn. Hãy để tôi giải thích: làm Blah.valueOf("A")
việc, nhưng Blah.valueOf("a")
sẽ không làm việc. Sau đó, một lần nữa Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
sẽ làm việc.
chỉnh sửa
thay đổi toUpperCase
để toUpperCase(Locale.ENGLISH)
dựa trên tc. bình luận và các tài liệu java
chỉnh sửa2
Trên Android bạn nên sử dụng Locale.US
, như sulai chỉ ra .
Locale.US
cho đầu vào / đầu ra có thể đọc được của máy.
Đây là một phương pháp có thể làm điều đó cho bất kỳ Enum nào và không phân biệt chữ hoa chữ thường.
/**
* 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()
));
}
equalsIgnoreCase
là cách để đi. +1
Sử dụng Blah.valueOf(string)
là tốt nhất nhưng bạn cũng có thể sử dụng Enum.valueOf(Blah.class, string)
.
Trong Java 8 trở lên, sử dụng Luồng :
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();
}
}
Nếu bạn không muốn viết tiện ích của riêng mình, hãy sử dụng Google trái ổi thư viện:
Enums.getIfPresent(Blah.class, "A")
Không giống như chức năng java tích hợp, nó cho phép bạn kiểm tra xem A có trong Blah không và không có ngoại lệ.
2 xu của tôi ở đây: sử dụng Luồng Java8 + kiểm tra một chuỗi chính xác:
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));
}
}
** BIÊN TẬP **
Đổi tên hàm thành fromString()
từ khi đặt tên cho nó bằng cách sử dụng quy ước đó, bạn sẽ nhận được một số lợi ích từ chính ngôn ngữ Java; ví dụ:
switch
các khối dễ đọc hơn , bạn có thể .orElse(null)
thay vì .orElseThrow()
đó để bạn có thể viết mã ném ngoại lệ trong default
mệnh đề - và bao gồm thông tin hữu ích hơn khi được yêu cầu. Và để làm cho nó dễ dàng hơn bạn có thể sử dụngv -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Optional
từ findFirst()
, cho phép người dùng quyết định nếu anh ta muốn .orElse(null)
, orElseThrow()
hoặc bất cứ điều gì ....
public static MyEnum valueOf(String)
thực sự là một lỗi biên dịch, vì nó giống như lỗi được định nghĩa ngầm, vì vậy phiên bản cũ hơn của câu trả lời của bạn thực sự tốt hơn. ( jls , ideone )
Bạn có thể cần điều này:
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;
}
}
Thêm một bổ sung:
public static String fromEnumName(String parameterName) {
if (parameterName != null) {
for (DQJ objType : DQJ.values()) {
if (parameterName.equalsIgnoreCase(objType.name())) {
return objType.parameterName;
}
}
}
return null;
}
Điều này sẽ trả về cho bạn Giá trị theo Tên Enum được xâu chuỗi Ví dụ: nếu bạn cung cấp "PERSON" trong fromEnumName, nó sẽ trả về cho bạn Giá trị của Enum tức là "Người"
Một cách khác để làm điều này bằng cách sử dụng phương thức tĩnh ẩn name()
của Enum. Tên sẽ trả về chuỗi chính xác được sử dụng để tạo enum có thể được sử dụng để kiểm tra đối với chuỗi được cung cấp:
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");
}
}
Kiểm tra:
System.out.println(Blah.getEnum("B").name());
//it will print B B
nguồn cảm hứng: 10 ví dụ về Enum trong Java
valueOf
làm cho bạn. Phương pháp tĩnh này không cung cấp thêm bất cứ điều gì, ngoại trừ et tất cả. Sau đó, các cấu trúc if / other rất nguy hiểm ... bất kỳ hằng số enum mới nào được thêm vào sẽ khiến phương thức này bị phá vỡ mà không thay đổi.
name()
không tĩnh.
Giải pháp sử dụng thư viện Guava. Phương thức getPlanet () không phân biệt chữ hoa chữ thường, vì vậy getPlanet ("MerCUrY") sẽ trả về Planet.MERCURY.
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();
}
}
Để thêm vào các câu trả lời trước đó và giải quyết một số cuộc thảo luận xung quanh null và NPE tôi đang sử dụng Tùy chọn Guava để xử lý các trường hợp vắng mặt / không hợp lệ. Điều này hoạt động rất tốt cho phân tích cú pháp URI / tham số.
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();
}
}
}
Đối với những người không biết, đây là một số thông tin khác về cách tránh null với Tùy chọn: https://code.google.com.vn/p/guava-lologists/wiki/UsingAndAvoidingNullExplained#Optional
Trong Java 8, mẫu Bản đồ tĩnh thậm chí còn dễ dàng hơn và là phương thức được ưu tiên của tôi. Nếu bạn muốn sử dụng Enum với Jackson, bạn có thể ghi đè lênString và sử dụng tên đó thay vì tên, sau đó chú thích bằng@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;
}
Phương pháp O (1) lấy cảm hứng từ mã được tạo tiết kiệm sử dụng hàm băm.
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 rất hữu ích, tôi đã sử dụng Enum
rất nhiều để thêm mô tả cho một số trường bằng các ngôn ngữ khác nhau, như ví dụ sau:
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;
}
}
Và sau đó, bạn có thể truy xuất mô tả một cách linh hoạt dựa trên mã ngôn ngữ được truyền cho getDescription(String lang)
phương thức, ví dụ:
String statusDescription = Status.valueOf("ACT").getDescription("en");
java.lang.Enum
định nghĩa một số phương thức hữu ích, có sẵn cho tất cả các kiểu liệt kê trong Java:
name()
phương thức để lấy tên của bất kỳ hằng số Enum nào. Chuỗi ký tự được sử dụng để viết hằng enum là tên của họ.values()
Phương pháp tương tự có thể được sử dụng để lấy một mảng của tất cả các hằng số Enum từ một loại Enum.valueOf()
phương thức để chuyển đổi bất kỳ Chuỗi nào thành hằng số Enum trong Java, như được hiển thị bên dưới.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
Trong đoạn mã này, valueOf()
phương thức trả về một Enum hằng giới tính.MALE, gọi tên trên trả về đó "MALE"
.
Thư viện commons-lang của Apache có hàm tĩnh org.apache.commons.lang3.EnumUtils.getEnum sẽ ánh xạ một Chuỗi thành loại Enum của bạn. Câu trả lời tương tự về cơ bản là Geoffreys nhưng tại sao lại tự lăn lộn khi nó ở ngoài tự nhiên.
Thêm vào câu trả lời được xếp hạng hàng đầu, với một tiện ích hữu ích ...
valueOf()
đưa ra hai trường hợp ngoại lệ khác nhau trong trường hợp không thích đầu vào của nó.
IllegalArgumentException
NullPointerExeption
Nếu các yêu cầu của bạn là như vậy mà bạn không có bất kỳ đảm bảo nào rằng Chuỗi của bạn chắc chắn sẽ khớp với giá trị enum, ví dụ: nếu dữ liệu Chuỗi đến từ cơ sở dữ liệu và có thể chứa phiên bản cũ của enum, thì bạn sẽ cần xử lý các thường ...
Vì vậy, đây là một phương thức có thể sử dụng lại mà tôi đã viết cho phép chúng ta xác định Enum mặc định được trả về nếu Chuỗi chúng ta vượt qua không khớp.
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;
}
}
Sử dụng nó như thế này:
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
}
Vì một sự đảo ngược switch
chưa được đề cập nhưng tôi giới thiệu nó (sử dụng lại enum của OP):
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);
}
}
}
Vì điều này không cung cấp bất kỳ giá trị bổ sung nào cho valueOf(String name)
phương thức, nên việc xác định một phương thức bổ sung nếu chúng ta muốn có một hành vi khác là điều hợp lý. Nếu chúng tôi không muốn nâng cao, IllegalArgumentException
chúng tôi có thể thay đổi việc triển khai thành:
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;
}
}
}
Bằng cách cung cấp một giá trị mặc định chúng tôi giữ hợp đồng của Enum.valueOf(String name)
không ném một IllegalArgumentException
theo cách mà rằng trong mọi trường hợp không null
được trả lại. Vì vậy, chúng tôi ném một NullPointerException
nếu tên là null
và trong trường hợp default
nếu defaultValue
là null
. Đó là cách làm valueOfOrDefault
việc.
Cách tiếp cận này thông qua thiết kế của Map
-Interface cung cấp một phương thức Map.getOrDefault(Object key, V defaultValue)
như Java 8.
Một tiện ích khác chụp theo cách ngược lại. Sử dụng một giá trị xác định Enum đó, không phải từ tên của nó.
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;
}
}
Thí dụ:
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")
trả về Foo.THREE
, bởi vì nó sẽ sử dụng getValue
để khớp với "drei", là phương thức công khai duy nhất, không phải là phương thức cuối cùng và không tĩnh trong Foo. Trong trường hợp Foo có nhiều hơn phương thức công khai, không phải cuối cùng và không tĩnh, ví dụ, getTranslate
trả về "drei", phương thức khác có thể được sử dụng : EnumUtil.from(Foo.class, "drei", "getTranslate")
.
Tạo một phần mở rộng và sau đó gọi valueOf<MyEnum>("value")
. Nếu loại không hợp lệ, bạn sẽ nhận được null và phải xử lý nó
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Ngoài ra, bạn có thể đặt giá trị mặc định, gọi valueOf<MyEnum>("value", MyEnum.FALLBACK)
và tránh phản hồi null. Bạn có thể mở rộng enum cụ thể của mình để mặc định là tự động
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
}
}
Hoặc nếu bạn muốn cả hai, hãy tạo cái thứ hai:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
Tôi thích sử dụng loại quy trình này để phân tích các lệnh dưới dạng chuỗi thành liệt kê. Tôi thường có một trong những bảng liệt kê là "không xác định" vì vậy sẽ giúp trả lại khi không tìm thấy những thứ khác (ngay cả trên cơ sở không nhạy cảm) chứ không phải là null (nghĩa là không có giá trị). Do đó tôi sử dụng phương pháp này.
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;
}
Cách nhanh nhất để có được tên của enum là tạo một bản đồ văn bản enum và giá trị khi ứng dụng bắt đầu và để có được tên gọi hàm Blah.getEnumName ():
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")
phương pháp này phân biệt chữ hoa chữ thường và không dung thứ khoảng trắng bên ngoài, do đó, giải pháp thay thế được đề xuất dưới đây bởi @ JoséMi.