13

I've seen two approaches to handling enums with properties. Is one better than the other?

As a property:

public enum SEARCH_ENGINE {
    GOOGLE("http://www.google.com"),
    BING("http://www.bing.com");

    private final String url;

    private SEARCH_ENGINE(String url) {
        this.url = url;
    }

    public String getURL() {
        return url;
    }
}

As a method:

public enum SEARCH_ENGINE {
    GOOGLE {
        public String getURL() {return "http://www.google.com";}
    },
    BING {
        public String getURL() {return "http://www.bing.com";}
    };

    public abstract String getURL();
}
JustinKSU
  • 4,875
  • 2
  • 29
  • 51
  • Does the second variant actually compile? It appears to be creating separate *classes* for each enum constant (which is the only way that you could override getURL(). The first is definitely nicer. – Anon May 12 '11 at 20:05
  • Personally, I like the second one better. It's more flexible. But essentially they are doing the same thing. – mellamokb May 12 '11 at 20:06
  • @mellamokb - the *behavior* may be the same. How it gets translated into bytecode and executed are very different (and yes, to answer my earlier question, it does compile, and it does create anonymous subclasses) – Anon May 12 '11 at 20:08
  • I always use the first one. I never used the second method to create enums. – Ravi Wallau May 12 '11 at 20:09
  • @Anon. I had no idea it created a subclass. Does that mean it's less efficient? – JustinKSU May 12 '11 at 20:10
  • 3
    @JustinKSU: Well, it means the JIT is less likely to be able to inline it. I think the chances of it being significant are pretty much nil though. – Jon Skeet May 12 '11 at 20:10
  • If that isn't just a very simple example, I think you should make url public final as Strings are immutable. And no, the second variant is not less efficient. – Kijewski May 12 '11 at 20:15
  • @Kay Someone else pointed that out. I updated the variable to be final. Would you really want to make it public? – JustinKSU May 12 '11 at 20:17
  • @JustingKSU: yes, I would make it public. There aren't any drawbacks. The JIT could do much better work if url was public, since accessing it wouldn't require any calls but only pointer arithmetic. – Kijewski May 12 '11 at 20:20

3 Answers3

20

The first clearly looks cleaner to me - it makes use of the commonality that each element of the enum will have a fixed String URL which is known at initialization. You're effectively repeating that "logic" in each implementation in the second version. You're overriding a method to provide the same logic ("just return a string which is known at compile-time") in each case. I prefer to reserve overriding for changes in behaviour.

I suggest making the url field private though, in the first.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I agree. I usually use case 1 when I don't have any logic, just constants, and case 2 when I have logic. – Kaj May 12 '11 at 20:12
  • 1. url is private... 2. The downside to this approach I see is when there are multiple proprieties. It is nice to see the value next to the property in which is associated instead of having to check the constructor. – JustinKSU May 12 '11 at 20:13
  • @JustinKSU: Yes, it's private and certainly should be - but IMO it should *also* be final. – Jon Skeet May 12 '11 at 20:14
0

Take a look at item 21 from this chapter of Josh Bloch's Effective Java. It talks about the type safe enum pattern.

John Kane
  • 4,383
  • 1
  • 24
  • 42
0

I'd go with the first since the compiler complains if you somehow forget to add a url. The second would let you make errors here.

DerMike
  • 15,594
  • 13
  • 50
  • 63
  • 1
    In the second approach the compiler will complain if you don't override the getURL() method achieving the same purpose. – JustinKSU May 12 '11 at 20:27
  • In the second the compiler complains, too: ` is not abstract and does not override abstract method getURL() in SEARCH_ENGINE`. – Kijewski May 12 '11 at 20:27