Override valueof() and toString() in Java enum

JavaEnumsOverridingTostringValue Of

Java Problem Overview


The values in my enum are words that need to have spaces in them, but enums can't have spaces in their values so it's all bunched up. I want to override toString() to add these spaces where I tell it to.

I also want the enum to provide the correct enum when I use valueOf() on the same string that I added the spaces to.

For example:

public enum RandomEnum
{
     StartHere,
     StopHere
}

Call toString() on RandomEnum whose value is StartHere returns string "Start Here". Call valueof() on that same string ("Start Here") returns enum value StartHere.

How can I do this?

Java Solutions


Solution 1 - Java

You can try out this code. Since you cannot override valueOf method you have to define a custom method (getEnum in the sample code below) which returns the value that you need and change your client to use this method instead.

public enum RandomEnum {
	
	StartHere("Start Here"),
	StopHere("Stop Here");
	
	private String value;
	
	RandomEnum(String value) {
		this.value = value;
	}
	
	public String getValue() {
		return value;
	}
	
	@Override
	public String toString() {
	    return this.getValue();
	}
	
	public static RandomEnum getEnum(String value) {
		for(RandomEnum v : values())
			if(v.getValue().equalsIgnoreCase(value)) return v;
		throw new IllegalArgumentException();
	}
}

Solution 2 - Java

Try this, but i don't sure that will work every where :)

public enum MyEnum {
    A("Start There"),
    B("Start Here");

    MyEnum(String name) {
        try {
            Field fieldName = getClass().getSuperclass().getDeclaredField("name");
            fieldName.setAccessible(true);
            fieldName.set(this, name);
            fieldName.setAccessible(false);
        } catch (Exception e) {}
    }
}

Solution 3 - Java

You can use a static Map in your enum that maps Strings to enum constants. Use it in a 'getEnum' static method. This skips the need to iterate through the enums each time you want to get one from its String value.

public enum RandomEnum {

    StartHere("Start Here"),
    StopHere("Stop Here");

    private final String strVal;
    private RandomEnum(String strVal) {
        this.strVal = strVal;
    }

    public static RandomEnum getEnum(String strVal) {
        if(!strValMap.containsKey(strVal)) {
            throw new IllegalArgumentException("Unknown String Value: " + strVal);
        }
        return strValMap.get(strVal);
    }

    private static final Map<String, RandomEnum> strValMap;
    static {
        final Map<String, RandomEnum> tmpMap = Maps.newHashMap();
        for(final RandomEnum en : RandomEnum.values()) {
            tmpMap.put(en.strVal, en);
        }
        strValMap = ImmutableMap.copyOf(tmpMap);
    }

    @Override
    public String toString() {
        return strVal;
    }
}

Just make sure the static initialization of the map occurs below the declaration of the enum constants.

BTW - that 'ImmutableMap' type is from the Google guava API, and I definitely recommend it in cases like this.


EDIT - Per the comments:

  1. This solution assumes that each assigned string value is unique and non-null. Given that the creator of the enum can control this, and that the string corresponds to the unique & non-null enum value, this seems like a safe restriction.
  2. I added the 'toSTring()' method as asked for in the question

Solution 4 - Java

How about a Java 8 implementation? (null can be replaced by your default Enum)

public static RandomEnum getEnum(String value) {
	return Arrays.stream(RandomEnum.values()).filter(m -> m.value.equals(value)).findAny().orElse(null);
}

Or you could use:

...findAny().orElseThrow(NotFoundException::new);

Solution 5 - Java

I don't think your going to get valueOf("Start Here") to work. But as far as spaces...try the following...

static private enum RandomEnum {
    R("Start There"), 
    G("Start Here"); 
    String value;
    RandomEnum(String s) {
        value = s;
    }
}

System.out.println(RandomEnum.G.value);
System.out.println(RandomEnum.valueOf("G").value);

Start Here
Start Here

Solution 6 - Java

The following is a nice generic alternative to valueOf()

public static RandomEnum getEnum(String value) {
  for (RandomEnum re : RandomEnum.values()) {
    if (re.description.compareTo(value) == 0) {
      return re;
    }
  }
  throw new IllegalArgumentException("Invalid RandomEnum value: " + value);
}

Solution 7 - Java

You still have an option to implement in your enum this:

public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name){...}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWildBamaBoyView Question on Stackoverflow
Solution 1 - JavaJugal ShahView Answer on Stackoverflow
Solution 2 - JavaBatView Answer on Stackoverflow
Solution 3 - JavapedorroView Answer on Stackoverflow
Solution 4 - JavacorlaezView Answer on Stackoverflow
Solution 5 - JavaJava42View Answer on Stackoverflow
Solution 6 - JavaexceptionView Answer on Stackoverflow
Solution 7 - JavaAndrey LebedenkoView Answer on Stackoverflow