16

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?

BenH
  • 2,100
  • 2
  • 22
  • 33
scphantm
  • 4,293
  • 8
  • 43
  • 77

5 Answers5

18

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;
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • yea, i guess im going to have to do it this way. just was hoping i wouldn't have to change so much. thanks – scphantm Oct 05 '11 at 14:09
  • Yeah not sure why Java doesn't allow this.. overridding 'valueOf' would make a lot more sense than implementing your own and having clients of your enum need to learn your convention.. – Roy Truelove Dec 19 '11 at 15:15
  • I'm not sure, but I think your method implementation actually requires the enum to have an additional `getName()` method. I think you should really be using the built-in `name()` to get the actual name of the enum. – schneida May 09 '17 at 13:02
  • @schneida indeed. Code changed. – JB Nizet May 09 '17 at 13:09
  • 1
    `O(n)`. tsk-tsk. – juanchito Jul 22 '21 at 15:29
11

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.

Arend v. Reinersdorff
  • 4,110
  • 2
  • 36
  • 40
2

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.

Stuart Cook
  • 3,994
  • 25
  • 23
dinigo
  • 6,872
  • 4
  • 37
  • 48
2

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;
}
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • 1
    I wanted to call it valueOf because its referenced in dozens of other classes that are part of XML binding. If I could override the valueof, then I didn't have to change my bindings at all, they would use my method by default. But, if I were forced to create a new method, I would have to update those dozens of bindings. Which is what I ended up having to do. – scphantm Mar 12 '13 at 15:11
0

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){
       ...
     }
}
John B
  • 32,493
  • 6
  • 77
  • 98