I need to re-implement the enum.valueof method of a few of my enumerations so they no longer throw exceptions, instead they simply return null if a value doesn't exist in the enumeration.
I'm trying the basic
#Override
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name){
but it's not working, saying I need to override or implement a super type.
I can come up with a super class I guess, but I'm just not sure how to put this together. Any ideas?
You can't. You'll have to define another, different method. The valueOf method is automatically generated by the compiler.
public static MyEnum permissiveValueOf(String name) {
for (MyEnum e : values()) {
if (e.name().equals(name)) {
return e;
}
}
return null;
}
Use Apache Commons Lang:
MyEnum myEnum = EnumUtils.getEnum(MyEnum.class, "MY_ENUM_VALUE");
Quote from the Javadoc for EnumUtils.getEnum:
Gets the enum for the class, returning null if not found.
This method differs from Enum.valueOf(java.lang.Class,
java.lang.String) in that it does not throw an exception for an
invalid enum name.
Is it absolutely necessary that the method is called valueOf like the method that enums have automatically? In the project that I'm currently working on we have similar methods, but we call them differently; for example, forName:
public static ESomeEnum forName(String name) {
for (ESomeEnum e : ESomeEnum.values()) {
if (e.name().equals(name)) {
return e;
}
}
return null;
}
You don't have to override valueOf. Here's what I did:
I had to "parse" some strings to enums and they didn't match with their declaration names, so I did a sort of reimplementation of valueOf(String name).
public enum Command {
DIR("DIR"),
PUT("PUT"),
GET("GET"),
OK("OK"),
ERROR("ERROR"),
READY("READY"),
FIN("#FIN#");
private String name;
private Command(final String name) {
this.name = name;
}
/**
* Returns the desired Enum or throws an exception
* #param commandName - String with the name contained by the Enum that you want
* #return Command
*/
public static Command getEnum(String commandName){
// if the string is "#FIN#" returns Command.FIN.
if(FIN.toString().equals(commandName)){
return FIN;
}
// if the name matches any of the remaining enums return whichever one matches
else if(Arrays.asList(Command.values()).contains(Command.valueOf(commandName))){
return Command.valueOf(commandName);
}
// if it still wasn't found, throw an exception
throw new IllegalArgumentException("No enum defined for this string: " + commandName);
}
#Override
public String toString(){
return name;
}
}
This code is tested and works.
You can use like:
Command k = Command.getEnum("#FIN#");
System.out.println(k.name() + " " +k.toString());
k = Command.getEnum("PUT");
System.out.println(k.name() + " " +k.toString());
And it's output would be:
FIN #FIN#
PUT PUT
Hope it helps.
You might consider creating a new (different name such as convert) static method in your enum classes.
public enum MyEnum{
....
public static MyEnum convert(Object value){
...
}
}
Related
I am using enum in java, Here is the enum
public enum AbuseSectionType{
MUSIC("Music"), DANCE("Dance"), SOLO("Solo"), ACT("Act")
private String displayString;
AbuseSectionType(String displayValue) {
this.displayString = displayValue;
}
#JsonValue
public String getDisplayString() {
return displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
}
I am trying to get value AbuseSectionType.valueOf("Music"). I am getting no enum constant and found no error. I am supposed to have value MUSIC.
The name() of an enum is the name specified when declaring it, MUSIC in your case.
If we read the javadoc for valueOf():
Returns the enum constant of the specified enum type with the
specified name.
valueOf() is using the name() of the enum. But what you want to achieve is different, so you cannot use this method. What you can do instead is to make your own method that finds the value from your own field (displayString).
Here's an example:
public static AbuseSectionType fromDisplayString(String displayString)
{
for(AbuseSectionType type : AbuseSectionType.values())
if(type.getDisplayString().equals(displayString)
return type;
return null; //not found
}
The default valuOf() method will only retrieve the respective enmum if the exact spelling of the enum-definition is used. In your case you have defined the enum MUSIC so in order to get that one you have to do it like this: AbuseSectionType.valueOf("MUSIC");
In order to achieve what you seem to want you have to implement a method in the enum class by yourself. For your example you could do somthing like this:
public AbuseSectionType resolve(String name) {
for(AbuseSectionType current : AbuseSectionType.values()) {
if(current.displayString.equals(name)) {
return current;
}
}
return null;
}
use AbuseSectionType.valueOf("MUSIC") pass the name of enum. See java docs regarding use of valueOf
I am using java 6 and my application is huge and its developed in java 6.
Now we trying to upgrade java version as 7.
But when i tried it to java 7 it will give compilation error in enum class.
In enum class i have defined valueOf() method so in java 7 it gives compilation error .
Code
public enum TestEnum {
TESTONE,TESTTWO, NONE;
public String toString() {
switch(this) {
case TESTONE:
return "Test one";
case TESTTWO:
return "Test two";
case NONE:
return "None";
}
return null;
};
public static TestEnum valueOf(Class<TestEnum> enumType, String value){
if(value.equalsIgnoreCase(TESTONE.toString()))
return TestEnum.TESTONE;
else if(value.equalsIgnoreCase(TESTTWO.toString()))
return TestEnum.TESTTWO;
else if(value.equalsIgnoreCase(NONE.toString()))
return TestEnum.NONE;
else
return null;
}
}
Error
Name clash: The method valueOf(Class<TestEnum>, String) of type TestEnum has the
same erasure as valueOf(Class<T>, String) of type Enum<E> but does not hide it TestEnum.java
Update(Resolved)
I changes valueOf() method and my file is compile.
public static TestEnum valueOf(TestEnum enumType, String value){
if(value.equalsIgnoreCase(TESTONE.toString()))
return TestEnum.TESTONE;
else if(value.equalsIgnoreCase(TESTTWO.toString()))
return TestEnum.TESTTWO;
else if(value.equalsIgnoreCase(NONE.toString()))
return TestEnum.NONE;
else
return null;
}
I'm not sure why it was working in Java 6, as [a method with that signature previously existed in Java 6](https://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html#valueOf(java.lang.Class, java.lang.String)) (and has since Java 5).
However, for the sake of your developers' sanity, I would strongly recommend that you rename the method anyway: Enum.valueOf does something well-known, and you are attempting to provide a method which does something different. This would violate the principle of least surprise, and likely lead to unintentional results.
A name like TestEnum.forName(String) is a possible alternative.
Additionally: a switch in an enum over a variable of the type of that enum is a bit of a code smell. You can express the enum more nicely:
enum TestEnum {
TESTONE("Test one"),TESTTWO("Test two"), NONE("None");
private String str;
private TestEnum(String str) {
this.str = str;
}
#Override public String toString() {
return str;
}
}
which has the additional advantage of you not being able to accidentally omit the "string" form of any further enum values you add.
Similarly, you can do better than explicitly testing the string values:
enum TestEnum {
/* values */;
private static HashMap<String, TestEnum> forNameMapping;
{
forNameMapping = new HashMap<>();
for (TestEnum t : TestEnum.values()) {
forNameMapping.put(t.str.toLowerCase(), t);
}
}
public static TestEnum forName(String str) {
return forNameMapping.get(str.toLowerCase());
}
}
Every enum is a subclass of Enum<T>. Enum<T> already defines a static method with the erasure valueOf(Class,String). Since static methods cannot be overridden, you cannot define a static method with the same signature. You will have to call your method differently.
For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}
I'd like to write an exception class which is usable with different classes and specific behaviors. It works well with changing an object - like
a.setWeight(500)
- but it doesn't work in my constructor - like
Cheese b = new Cheese(500);
because the object is not being generated and null is inserted in my WeightException.
public class WeightException extends Exception {
private int attribute;
private Object object;
public WeightException(Object o, int a) throws WeightException {
object = o;
attribute = a;
}
public String getMessage() {
if(object instanceof Cheese)
return "Cheese is overweight.";
if(object instanceof Baggage)
return "Baggage is "+String.valueOf(attribute)+" kilos overweight.";
}
}
public class Cheese {
private int weight;
public Cheese(int weight) {
setWeight(weight);
}
public void setWeight(int weight) throws WeightException {
if(weight<200)
this.weight = weight;
else
throw new WeightException(this, weight);
}
}
Does anybody know a better approach to solve this than to insert a string with the class name in my exception class parameters?
Implement an interface in the classes you want to use with this exception.
The interface has a method to define a message, possible another to provide an attribute.
Alternatively, provide an array of attributes and use String.format to build the message.
Use that interface to define the object parameter passed in to the exception ctor.
Call that method in the exception to get the message.
Personally, I find this to be an anti-pattern, unless the classes you want to use with the exception are very tightly related. Otherwise you're giving up semantically-meaningful exception property names.
I'd rather see an app-specific superclass with subclasses with semantic meaning.
Here is a solution which would require that you use a "toy" project of mine (well, I already use it in other projects):
Make a base abstract class like this:
public abstract class WeightedItem
{
protected static final MessageBundle BUNDLE;
static {
// The day when you get serious, replace with a properties bundle
final MessageSource source = MapMessageSource.newBuilder()
.put(Cheese.class.getCanonicalName(), "cheese is overweight")
.put(Baggage.class.getCanonicalName(), "baggage is %d kilos overweight")
.build();
BUNDLE = MessageBundle.newBuilder().appendSource(source).freeze();
}
protected int weight;
protected final WeightException doException(final Object... params)
{
return new WeightException(BUNDLE.printf(getClass().getCanonicalName(),
params));
}
}
An implementation of Baggage would then do:
public class Baggage
extends WeightedItem
{
// ....
public void setWeight(int weight)
throws WeightException
{
if (overweight)
throw doException(weight);
}
}
As the implementation is both key-resistant (returns the key if missing) and format-resistant (returns the format string itself if format argument mismatch) you are guaranteed to have parameterized messages or quickly see where you got your messages wrong...
Have you actually tried running this code? The this variable is valid (non-null) within a constructor. Even if the constructor throws an exception, a new object has been created and can be referenced. See the JLS.
If you parameterize the exception with everything you need for the message, you can rid yourself of using instanceof, and make the exception usable by any class:
Also, it's not a good idea to hold a reference to the object that caused the exception - it's unnecessary, is a form of memory leak, but importantly if the exception is thrown from the constructor, will allow this to "escape" from the constructor (always bad).
public class WeightException extends Exception {
private final int attribute;
private final String className;
private final String units;
public WeightException(Object o, int a) {
this(o, a, null);
}
public WeightException(Object o, int a, String u) {
classname = o.getClass().getSimpleName(); // eg "Cheese"
attribute = a;
units = u == null ? "" : u + " ";
}
public String getMessage() {
return className " is " + attribute + " " + units + "overweight.";
}
}
You can now use this exception with any class without further modification of the exception or the client class, other than to provide the optional units:
From Cheese:
throw new WeightException(this, weight);
From Baggage:
throw new WeightException(this, weight, "kilos");
I have a large number of Enums that implement this interface:
/**
* Interface for an enumeration, each element of which can be uniquely identified by its code
*/
public interface CodableEnum {
/**
* Get the element with a particular code
* #param code
* #return
*/
public CodableEnum getByCode(String code);
/**
* Get the code that identifies an element of the enum
* #return
*/
public String getCode();
}
A typical example is:
public enum IMType implements CodableEnum {
MSN_MESSENGER("msn_messenger"),
GOOGLE_TALK("google_talk"),
SKYPE("skype"),
YAHOO_MESSENGER("yahoo_messenger");
private final String code;
IMType (String code) {
this.code = code;
}
public String getCode() {
return code;
}
public IMType getByCode(String code) {
for (IMType e : IMType.values()) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
}
}
As you can imagine these methods are virtually identical in all implementations of CodableEnum. I would like to eliminate this duplication, but frankly don't know how. I tried using a class such as the following:
public abstract class DefaultCodableEnum implements CodableEnum {
private final String code;
DefaultCodableEnum(String code) {
this.code = code;
}
public String getCode() {
return this.code;
}
public abstract CodableEnum getByCode(String code);
}
But this turns out to be fairly useless because:
An enum cannot extend a class
Elements of an enum (SKYPE, GOOGLE_TALK, etc.) cannot extend a class
I cannot provide a default implementation of getByCode(), because DefaultCodableEnum is not itself an Enum. I tried changing DefaultCodableEnum to extend java.lang.Enum, but this doesn't appear to be allowed.
Any suggestions that do not rely on reflection?
Thanks,
Don
You could factor the duplicated code into a CodeableEnumHelper class:
public class CodeableEnumHelper {
public static CodeableEnum getByCode(String code, CodeableEnum[] values) {
for (CodeableEnum e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
Each CodeableEnum class would still have to implement a getByCode method, but the actual implementation of the method has at least been centralized to a single place.
public enum IMType implements CodeableEnum {
...
public IMType getByCode(String code) {
return (IMType)CodeableEnumHelper.getByCode(code, this.values());
}
}
Abstract enums are potentially very useful (and currently not allowed). But a proposal and prototype exists if you'd like to lobby someone in Sun to add it:
http://freddy33.blogspot.com/2007/11/abstract-enum-ricky-carlson-way.html
Sun RFE:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766
To tidy up dave's code:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> E getByCode(
String code, E[] values
) {
for (E e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
public enum IMType implements CodableEnum {
...
public IMType getByCode(String code) {
return CodeableEnumHelper.getByCode(code, values());
}
}
Or more efficiently:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> Map<String,E> mapByCode(
E[] values
) {
Map<String,E> map = new HashMap<String,E>();
for (E e : values) {
map.put(e.getCode().toLowerCase(Locale.ROOT), value) {
}
return map;
}
}
public enum IMType implements CodableEnum {
...
private static final Map<String,IMType> byCode =
CodeableEnumHelper.mapByCode(values());
public IMType getByCode(String code) {
return byCode.get(code.toLowerCase(Locale.ROOT));
}
}
I had a similar issue with a localization component that I wrote. My component is designed to access localized messages with enum constants that index into a resource bundle, not a hard problem.
I found that I was copying and pasting the same "template" enum code all over the place. My solution to avoid the duplication is a code generator that accepts an XML configuration file with the enum constant names and constructor args. The output is the Java source code with the "duplicated" behaviors.
Now, I maintain the configuration files and the generator, not all of the duplicated code. Everywhere I would have had enum source code, there is now an XML config file. My build scripts detect out-of-date generated files and invoke the code generator to create the enum code.
You can see this component here. The template that I was copying and pasting is factored out into an XSLT stylesheet. The code generator runs the stylesheet transformation. An input file is quite concise compared to the generated enum source code.
HTH,
Greg
Unfortunately, I don't think that there is a way to do this. Your best bet would pro ably be to give up in emums altogether and use conventional class extension and static members. Otherwise, get used to duplicating that code. Sorry.
Create a type-safe utility class which will load enums by code:
The interface comes down to:
public interface CodeableEnum {
String getCode();
}
The utility class is:
import java.lang.reflect.InvocationTargetException;
public class CodeableEnumUtils {
#SuppressWarnings("unchecked")
public static <T extends CodeableEnum> T getByCode(String code, Class<T> enumClass) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
T[] allValues = (T[]) enumClass.getMethod("values", new Class[0]).invoke(null, new Object[0]);
for (T value : allValues) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
}
A test case demonstrating usage:
import junit.framework.TestCase;
public class CodeableEnumUtilsTest extends TestCase {
public void testWorks() throws Exception {
assertEquals(A.ONE, CodeableEnumUtils.getByCode("one", A.class));
assertEquals(null, CodeableEnumUtils.getByCode("blah", A.class));
}
enum A implements CodeableEnum {
ONE("one"), TWO("two"), THREE("three");
private String code;
private A(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
}
Now you are only duplicating the getCode() method and the getByCode() method is in one place. It might be nice to wrap all the exceptions in a single RuntimeException too :)
Here I have another solution:
interface EnumTypeIF {
String getValue();
EnumTypeIF fromValue(final String theValue);
EnumTypeIF[] getValues();
class FromValue {
private FromValue() {
}
public static EnumTypeIF valueOf(final String theValue, EnumTypeIF theEnumClass) {
for (EnumTypeIF c : theEnumClass.getValues()) {
if (c.getValue().equals(theValue)) {
return c;
}
}
throw new IllegalArgumentException(theValue);
}
}
The trick is that the inner class can be used to hold "global methods".
Worked pretty fine for me. OK, you have to implement 3 Methods, but those methods,
are just delegators.
It seems like you are actually implementing run time type information. Java provides this as a language feature.
I suggest you look up RTTI or reflection.
I don't think this is possible. However, you could use the enum's valueOf(String name) method if you were going to use the enum value's name as your code.
How about a static generic method? You could reuse it from within your enum's getByCode() methods or simply use it directly. I always user integer ids for my enums, so my getById() method only has do do this: return values()[id]. It's a lot faster and simpler.
If you really want inheritance, don't forget that you can implement the enum pattern yourself, like in the bad old Java 1.4 days.
About as close as I got to what you want was to create a template in IntelliJ that would 'implement' the generic code (using enum's valueOf(String name)). Not perfect but works quite well.
In your specific case, the getCode() / getByCode(String code) methods seems very closed (euphemistically speaking) to the behaviour of the toString() / valueOf(String value) methods provided by all enumeration. Why don't you want to use them?
Another solution would be not to put anything into the enum itself, and just provide a bi-directional map Enum <-> Code for each enum. You could e.g. use ImmutableBiMap from Google Collections for this.
That way there no duplicate code at all.
Example:
public enum MYENUM{
VAL1,VAL2,VAL3;
}
/** Map MYENUM to its ID */
public static final ImmutableBiMap<MYENUM, Integer> MYENUM_TO_ID =
new ImmutableBiMap.Builder<MYENUM, Integer>().
put(MYENUM.VAL1, 1).
put(MYENUM.VAL2, 2).
put(MYENUM.VAL3, 3).
build();
In my opinion, this would be the easiest way, without reflection and without adding any extra wrapper to your enum.
You create an interface that your enum implements:
public interface EnumWithId {
public int getId();
}
Then in a helper class you just create a method like this one:
public <T extends EnumWithId> T getById(Class<T> enumClass, int id) {
T[] values = enumClass.getEnumConstants();
if (values != null) {
for (T enumConst : values) {
if (enumConst.getId() == id) {
return enumConst;
}
}
}
return null;
}
This method could be then used like this:
MyUtil.getInstance().getById(MyEnum.class, myEnumId);