3

got a question around which one is better to use. Java5 Enums or static string.

I always get the data in form of Strings.

So for example,

private static final String LOAD_DRUGS = "load drugs";

or use Java5 enums

public enum LoadType
{
LOAD_DRUGS("load drugs");
}

In my code, I always receive "load drugs" kind of strings. I use if else statements to see what to do next based on it. But I am tending to use java5 enums and use switch case, but I always have to get the enum based of the string value I get.

So what are the pro's and con's of both ways??

Thanks!!

Rishi
  • 1,331
  • 4
  • 13
  • 16

4 Answers4

2

This answer is probably overkill. Maybe there's a badge for that. Anyway, it could be useful in a situation in which you have a lot of enumeration values and have to deal with a Strings as being the means by which another system sends information to you. That is exactly what I have (something north of 50), so I used this construct so that I could generate a mapping just once of the Strings reported by the db and the enums I used internally, and then not think about it after -- toString and fromString do all the work:

package com.stevej;

import com.google.common.collect.HashBiMap;

public enum TestEnum {
  ALPHA("Alpha"), BETA("Beta"), GAMMA("Gamma");

  private static HashBiMap<TestEnum, String> stringMapping = HashBiMap
      .create(TestEnum.values().length);

  private String stringValue = null;

  TestEnum(String stringValue) {
    this.stringValue = stringValue;
  }

  String getStringValue() {
    return this.stringValue;
  }

  @Override
  public String toString() {
    return stringMapping.get(this);
  }

  public static TestEnum fromString(String string) {
    return stringMapping.inverse().get(string);
  }

  static {
    for (TestEnum e : TestEnum.values()) {
      stringMapping.put(e, e.getStringValue());
    }
  }
}

Here's a quick test to show the data switching back and forth:

package com.stevej;

public class StackOverflowMain {

  public static void main(String[] args) {
    System.out.println(">> " + TestEnum.ALPHA);
    System.out.println(">> " + TestEnum.BETA);
    System.out.println(">> " + TestEnum.GAMMA);

    TestEnum a = TestEnum.fromString("Alpha");
    TestEnum b = TestEnum.fromString("Beta");
    TestEnum c = TestEnum.fromString("Gamma");

    System.out.println(">> " + a);
    System.out.println(">> " + b);
    System.out.println(">> " + c);
  }

}

The output shows the use of the mixed case values instead of the uppercase, showing my strings are being used:

>> Alpha
>> Beta
>> Gamma
>> Alpha
>> Beta
>> Gamma

Note that I am using the Google Guava library so I can take advantage of the BiMap.

Steve J
  • 2,676
  • 20
  • 18
  • I see JohnB is suggesting something along these lines. – Steve J Sep 28 '11 at 17:45
  • Since the `Map` is only navigated on one direction, a simple, standard `HashMap` will do also very nicely. – A.H. Sep 28 '11 at 17:49
  • The map is used in reverse in the static method fromString(). Also BiMap enforces the rule that the strings have to be as unique as the enumeration values. – Steve J Sep 28 '11 at 17:52
  • Sorry for being not clear enough: Since the map is used only in one direction - the inverse direction - you can use a simple `HashMap` and construct that inverse mapping in the static initializer. Dupicate strings are effectively not allowed. And since the `TestEnum` side will be checked for dups by the compiler, this is also no point for the BiMap. Besides of this minor point this is the way I have seen numerous `enum` definitions and also created them for myself. – A.H. Sep 28 '11 at 18:04
  • But I use the forward map for the toString operation. Maybe I'm missing something. Essentially I want to override the String<->Enum in both directions. My string representations for the enumeration values are the only ones that appear. – Steve J Sep 28 '11 at 18:06
  • I did not catch `toString`. But why not using "return this.stringValue;" inside `toString`? no need to lookup in the map. – A.H. Sep 28 '11 at 18:10
  • I could indeed have used this.stringValue. Using the same map for toString and fromString appeals to my sense of symmetry. Still, your suggestion is a good one, and more efficient. – Steve J Sep 28 '11 at 18:16
1

you can try a simple substitution for turn the string into an enum

switch(MyEnum.valueOf(text.replace(' ', '_')) {
    case load_strings:

You can use toUpperCase() if you want it in upper case.

You should do what you think is the simplest and clearest.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • @claymore1977, I agree. I'm not claiming its a good idea, but you can do it. ;) – Peter Lawrey Sep 28 '11 at 16:37
  • I am not asking ways to convert from string to enum. Just want to know what are the pro's and con's of using these methods. Thanks!! – Rishi Sep 28 '11 at 17:34
  • @Rishi, in that case I would say it doesn't matter much in your example. It makes more difference if you are going to use `enum` as objects that than a list of strings. – Peter Lawrey Sep 28 '11 at 17:37
  • The problems I see are those of maintenance and flexibility. From a maintenance point of view, this text.replace() is going to have to appear all over the place. If the pattern changes, then that's a lot of code to fix. And it assumes that the same pattern works for every enumeration. That might not be flexible enough. I would want a solution that matches the enumeration value to an arbitrary string, with the only restriction being that the strings must be unique across the enumeration values. That way I decouple the service that is delivering strings from my code that interprets them. – Steve J Sep 28 '11 at 17:48
  • @Steve J, So how would you handle spaces in Strings without adding a method call? – Peter Lawrey Sep 28 '11 at 17:49
  • @Peter: Can you give me an example? – Steve J Sep 28 '11 at 17:50
  • @SteveJ, The OP suggested `load drugs` – Peter Lawrey Sep 28 '11 at 17:53
  • Check out my answer below (http://stackoverflow.com/questions/7586418/using-enums-or-static-string-variable-in-java/7587147#7587147). I don't see spaces being a problem. – Steve J Sep 28 '11 at 17:54
  • @SteveJ, Your answer could be overkill in some situations, but in the general case (without more information) it may be the best solution. e.g. if Strings contain other characters, or case matters. – Peter Lawrey Sep 28 '11 at 17:59
  • "...it may be the best solution" -- using my Jedi mind powers, I compel you to up-vote my answer... and before I forget, these aren't the droids you're looking for. – Steve J Sep 28 '11 at 18:03
1

Generally you should use Enums to store a set of values that are related in some way. They all should have a similar "is a" relationship. It should not be used to simply store a set of constant strings that are not related.

Of course, if you have a switch statement over a set of string values then that suggests that those string values are related and should be grouped as an Enum and use enum's mechanism to use a switch.

The enum type's valueOf method will allow you to convert from a String to the enum type if the passed string is equal to the name value. If this is not the case, you could implement your own valueOf that uses a stored string field rather than the name. You could store the fields in a private static Map for the conversion.

John B
  • 32,493
  • 6
  • 77
  • 98
0

Because enum is typed.

Static String is not typed.

public enum Something{
  CAT("cat");

  private String animal;

  private Something(String animal){
    this.animal = animal;
  }

  public String getAnimal(){
    return this.animal;
  }
}
Oh Chin Boon
  • 23,028
  • 51
  • 143
  • 215
  • Aaprt from the type safety, can enums with switch/case assure more performance than string with if/else. I know how if/else and switch/case are considered in performance but looking in this context. – Rishi Sep 28 '11 at 17:37