enum valueOf IllegalArgumentException: No enum const class - java

I have used enums in java in the past but for some reason I am getting a strange error right now. the Line of code that it is throwing the error is:
switch(ConfigProperties.valueOf(line[0].toLowerCase()){
...
}
I am getting a
java.lang.IllegalArgumentException: No enum const class
allautomator.ConfigProperties.language
in the example line is an array of Strings.
I am just really confused right now, I do not know what could possibly be wrong.

The enum constants are case sensitive, so make sure you're constants are indeed lower case. Also, I would suggest that you trim() the input as well to make sure no leading / trailing white-space sneak in there:
ConfigProperties.valueOf(line[0].toLowerCase().trim())
For reference, here is a working sample program containing your line:
enum ConfigProperties { prop1, prop2 }
class Test {
public static void main(String[] args) {
String[] line = { "prop1" };
switch (ConfigProperties.valueOf(line[0].toLowerCase())) {
case prop1: System.out.println("Property 1"); break;
case prop2: System.out.println("Property 2"); break;
}
}
}
Output:
Property 1

I am using a similar concept, but having a default value in case of fail
public enum SortType {
PRICE_ASC("price_asc"),
PRICE_DESC("price_desc"),
MODEL_ASC("model_asc"),
MODEL_DESC("model_desc");
private String name;
SortType(String name) {
this.name = name;
}
public String getName() {
return name;
}
static public SortType lookup(String id, SortType defaultValue) {
try {
return SortType.valueOf(id);
} catch (IllegalArgumentException ex) {
return defaultValue;
}
}
}

Related

Check if class has a variable in its constructor based on a string?

Let's say I have a class named Person and its constructor had variables like name, age, hairColor and so on. If I had a function that receives a string that should match one of the class's variables, how could I check if that class actually had that variable and how could I go about modifying it? For example:
public class Person {
public String name;
public int age;
public String hairColor;
public Person() {
name = "Bryce";
age = 21;
hairColor = "brown";
}
public void changeHairColor(String variable, String color) {
if (/*this class contains the variable passed as an argument to this method*/) {
// Person[variable] = color
}
}
}
I'm a python dev, mostly, so the method changeHairColor has some pseudo-python in it. I want to be able to edit the variable in a similar way you could edit variables inside of dictionaries with Python:
person = {
"name": "Bryce",
"age": 21,
"hairColor": "brown"
}
def changeHairColor(variable, color):
person[variable] = color
If that is at all possible.
The only way to do it in Java is to use Java Reflection API:
public class Test {
public String name;
public int age;
public String hairColor;
public void setProperty(String property, Object value) {
try {
Field declaredField = this.getClass().getDeclaredField(property);
switch (declaredField.getAnnotatedType().getType().getTypeName()) {
case "java.lang.String":
declaredField.set(this, value);
break;
// handle other types
}
} catch (NoSuchFieldException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}
}
public static void main(String[] args) {
Test test = new Test();
test.setProperty("name", "Bob");
System.out.println(test.name);
}
}
I would not solve this with reflection. If your PlayerCharacter has an enumerable set of attributes, I would model these as a Java enum and store the attribute values within the PlayerCharacter object in an EnumMap:
import java.util.EnumMap;
public class PlayerCharacter {
public enum Attribute {
AGILITY,
DEXTERITY,
/* etc ...*/
VITALITY
}
private EnumMap<Attribute, Integer> attributes = new EnumMap<>(Attribute.class);
public PlayerCharacter() {
// initialize each attribute with a default value (0 in this example)
for (Attribute a : Attribute.values()) {
attributes.put(a, new Integer(0));
}
}
public int getValue(Attribute attribute) {
return attributes.get(attribute);
}
public void levelUp(Attribute attribute, int amount) {
attributes.put(attribute, attributes.get(attribute) + amount);
}
}
The biggest benefit of using an enum instead of plain old String (+reflection), is that this way you get compile-time type safety for the code that's using your PlayerCharacter.
Using Reflection API, you can access the methods and properties on an object at run time. The other answer describes its usage. But I don't recommend reflections for your problem. How about the following:
public void changeHairColor(String variable, String color) {
if("name".equalsIgnoreCase(variable))
this.name = color;
else if("age".equalsIgnoreCase(variable))
this.age = Integer.parseInt(color);
else if("color".equalsIgnoreCase(variable))
this.color = color;
else
throw new Exception ("error - property not available");
}
}
Note, your existing method name 'changeHairColor' doesn't make sense in the context. It should be someething like 'changeProperty' because you are not just changing the 'color', you are changing any available property with this method.

Default case in toString for enums

I am somewhat new to enums in Java, and I am trying to override toString() so that it can return special cases for an enum with creating code for each case:
enum TestEnum {
One, Two, Three,
Exclamation, Ampersand, Asterisk;
public String toString() {
if (this == Ampersand) return "&";
if (this == Exclamation) return "!";
if (this == Asterisk) return "*";
return null; // return toString(); ???
}
If I use toString as the default return statement, I obviously get a StackOverflowError. Is there a way to get around this and return any cases not included in the toString()?
Is there a way to get around this and return any cases not included in the toString()?
I think you just want:
return super.toString();
Then it won't call itself - it'll just use the superclass implementation.
However, I'd change the implementation to make the string representation a field within the enum value, specified at construction time where necessary:
enum TestEnum {
One, Two, Three,
Exclamation("!"), Ampersand("&"), Asterisk("*");
private final String name;
private TestEnum(String name) {
this.name = name;
}
private TestEnum() {
name = super.toString();
}
#Override public String toString() {
return name;
}
}
Tested with:
public class Test {
public static void main(String [] args){
for (TestEnum x : TestEnum.values()) {
System.out.println(x);
}
}
}
Output:
One
Two
Three
!
&
*

Java enum error - return type reqiued

I created simple enum class in java.
public enum XmlElementsInput {
element_sentenceInput("a");
element_sentence("b");
private final String elementName;
private XmlElementsInput(String name) {
this.elementName = name;
}
public String getElementName() {
return elementName;
}
}
But Netbeans say me: invalid method declaration; return type required, ilegal start of type on line element_sentence("b");. I dont know why? Can you tell me why?
The enum types must separated by comma:
element_sentenceInput("a"),
element_sentence("b");
Use commas to separate enum values, as follows:
public enum XmlElementsInput {
element_sentenceInput("a"),
element_sentence("b");
// Remaining part
}

Java enums and Objective-C enums

I have the following enum in Objective-C:
typedef enum {
APIErrorOne = 1,
APIErrorTwo,
APIErrorThree,
APIErrorFour
} APIErrorCode;
I use the indexes to reference an enum from an xml, for example, xml may have error = 2, which maps to APIErrorTwo
My flow is I get an integer from the xml, and run a switch statement as follows:
int errorCode = 3
switch(errorCode){
case APIErrorOne:
//
break;
[...]
}
Seems Java dislikes this kind of enum in a switch statement:
In Java it seems you can't assign indexes to enum members. How can I get a Java equivalent of the above ?
Java enums have a built-in ordinal, which is 0 for the first enum member, 1 for the second, etc.
But enums are classes in Java so you may also assign them a field:
enum APIErrorCode {
APIErrorOne(1),
APIErrorTwo(27),
APIErrorThree(42),
APIErrorFour(54);
private int code;
private APIErrorCode(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
}
One question per post is the general rule here.
But evolving the JB Nizer answer.
public enum APIErrorCode {
APIErrorOne(1),
APIErrorTwo(27),
APIErrorThree(42),
APIErrorFour(54);
private final int code;
private APIErrorCode(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
public static APIErrorCode getAPIErrorCodeByCode(int error) {
if(Util.errorMap.containsKey(error)) {
return Util.errorMap.get(error);
}
//Or create some default code
throw new IllegalStateException("Error code not found, code:" + error);
}
//We need a inner class because enum are initialized even before static block
private static class Util {
private static final Map<Integer,APIErrorCode> errorMap = new HashMap<Integer,APIErrorCode>();
static {
for(APIErrorCode code : APIErrorCode.values()){
errorMap.put(code.getCode(), code);
}
}
}
}
Then in your code you can write
int errorCode = 3
switch(APIErrorCode.getAPIErrorCodeByCode(errorCode){
case APIErrorOne:
//
break;
[...]
}

How to use enum with values in Java

When I try to use enum to store: "=", ">", "<", etc, I have:
public static enum DataValueModifier {
EQUAL("="),
GREATER_THAN(">"),
GREATER_EUQAL(">="),
LESS_THAN("<"),
LESS_EQUAL("<="),
APPRROXIMATE("~"),
NOT_DETERMINED("ND");
private String value;
private DataValueModifier(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
How do I use it when I try to compare a string to see if it contains a "=" sign, should I do:
if (dataValue.contains(DataValueModifier.EQUAL.getValue())) {
...
}
I understand using enum is the better practice here, but this just looks silly...
Thanks,
David
If you defined a method boolean containedIn(String str) in your enum and imported your enum values of interest (in this case EQUAL), usage would look like:
if (EQUAL.containedIn(dataValue)) {
...
}
First of all, I'd move the "contains" method (or the equivalent of it) to the enum itself by defining an isModifier method.
public static enum DataValueModifier {
...
public boolean isModifier( String modifierString )
{
return modifierString != null && value.equals(modifierString);
}
}
Then, your code looks like this instead:
if (DataValueModifier.EQUAL.isModifier(dataValue))
{
//...
}
But, more importantly, why are you using dataValue instead of the enum in the first place? If you are getting command line input or something or parsing a string equation and then need to figure out the expression I guess I understand. But if you have control of the code then you should just start with the enum and you'll be able to say
if ( dataValueEnum == DataValueModifier.EQUAL ) {
{
//...
}
I'd also consider adding a static method to the enum that converts a given string to the correct enum value. It's not quite as efficient, perhaps, but unless you really care about efficiency it will make your code much cleaner. So add this method to your enum:
public static DataValueModifier toDataValueModifier( String dataValue ) {
if( EQUAL.isModifier( dataValue ) {
return EQUAL;
} else if( GREATER_THAN.isModifier( dataValue ) {
return GREATER_THAN;
} else if...
// Do this for all possible values
} else {
return UNKNOWN;
// Also, add an UNKNOWN to your list of enum values.
}
}
The isModifier and the toDataValueModifier methods might add a bit of ugly code to your DataValueModifier enum, but all your other code will look great. You can now do something like this:
DataValueModifier dataValueEnum = DataValueModifier.toDataValueModifier(dataValue);
if (dataValueEnum == DataValueModifier.EQUAL) {
...
}
or even
switch( DataValueModifier.toDataValueModifier(dataValue) ) {
case EQUAL:
// ...
break;
case GREATER_THAN:
// ...
break;
case GREATER_EQUAL:
// ...
break;
// ... define all the cases you want
case UNKNOWN:
default:
// ...
}
I like to use a static import in these cases.
package mypackage;
public enum DataValueModifier
{
//your enum code
}
then...
import static mypackage.DataValueModifier.*;
public MyClass
{
// code blah blah blah
public void doIt()
{
// more code blah blah
if (dataValue.contains(EQUAL.getValue()))
{
//...
}
}
}
It's a little nicer.

Categories