是什么原因导致 java.lang.IllegalArgumentException: 没有枚举常量类,即使迭代通过 value()工作得很好?

这个问题基本上是我的 上一个问题的延伸。我问前面的问题是为了确保在类加载时填充 Enum 常量。下面是我的类,添加了一个简单的方法 getByName:

public enum PropName {


CONTENTS("contents"),
USE_QUOTES("useQuotes"),
ONKEYDOWN("onkeydown"),
BROWSER_ENTIRE_TABLE("browseEntireTable"),
COLUMN_HEADINGS("columnHeadings"),
PAGE_SIZE("pageSize"),
POPUP_TITLE("popupTitle"),
FILTER_COL("filterCol"),
SQL_SELECT("sqlSelect"),
;


private String name;


private PropName(String name) {
this.name = name;
}


public String getName() {
return name;
}


public static PropName getByName(String name){
return   PropName.valueOf(name);
}
}

对方法 getByName("columnHeadings")的调用抛出了 java.lang.IllegalArgumentException: No enum const class labware.web.component.limsgrid.PropName.columnHeadings,但是如果我用下面的代码替换这个方法,它就会正常工作。

 public static PropName getByName(String name){
for(PropName prop : values()){
if(prop.getName().equals(name)){
return prop;
}
}


throw new IllegalArgumentException(name + " is not a valid PropName");
}

知道我哪里做错了吗?

196555 次浏览

That's because you defined your own version of name for your enum, and getByName doesn't use that.

getByName("COLUMN_HEADINGS") would probably work.

Enum.valueOf() only checks the constant name, so you need to pass it "COLUMN_HEADINGS" instead of "columnHeadings". Your name property has nothing to do with Enum internals.


To address the questions/concerns in the comments:

The enum's "builtin" (implicitly declared) valueOf(String name) method will look up an enum constant with that exact name. If your input is "columnHeadings", you have (at least) three choices:

  1. Forget about the naming conventions for a bit and just name your constants as it makes most sense: enum PropName { contents, columnHeadings, ...}. This is obviously the most convenient.
  2. Convert your camelCase input into UPPER_SNAKE_CASE before calling valueOf, if you're really fond of naming conventions.
  3. Implement your own lookup method instead of the builtin valueOf to find the corresponding constant for an input. This makes most sense if there are multiple possible mappings for the same set of constants.

Instead of defining: COLUMN_HEADINGS("columnHeadings")

Try defining it as: COLUMNHEADINGS("columnHeadings")

Then when you call getByName(String name) method, call it with the upper-cased String like this: getByName(myStringVariable.toUpperCase())

I had the same problem as you, and this worked for me.

I had parsing enum problem when i was trying to pass Nullable Enum that we get from Backend. Of course it was working when we get value, but it was problem when the null comes up.

java.lang.IllegalArgumentException: No enum constant

Also the problem was when we at Parcelize read moment write some short if.

My solution for this was

1.Create companion object with parsing method.

enum class CarsType {
@Json(name = "SMALL")
SMALL,
@Json(name = "BIG")
BIG;


companion object {
fun nullableValueOf(name: String?) = when (name) {
null -> null
else -> valueOf(name)
}
}
}

2. In Parcerable read place use it like this

data class CarData(
val carId: String? = null,
val carType: CarsType?,
val data: String?
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
CarsType.nullableValueOf(parcel.readString()),
parcel.readString())