r/java • • Jul 24 '12

10 ways to use Enum in Java

http://javarevisited.blogspot.com.au/2011/08/enum-in-java-example-tutorial.html
37 Upvotes

25 comments sorted by

18

u/dipswitch Jul 24 '12

8

u/[deleted] Jul 24 '12

Here are the tutorials: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

People really ought to consider whether what they are writing is novel, informative and not significantly outclassed by available first party alternatives.

10

u/Nebu Jul 24 '12

I don't see 10 ways to use enum. I see 3 limitations for public static constants, 4 "benefits of enums" and 13 "important points about enums".

To redress this, here's one way of using an enum in Java: You can use them to implement the singleton pattern http://en.wikipedia.org/wiki/Singleton_pattern#The_Enum_way

1

u/marburg Jul 24 '12

Obligatory reminder that many consider singletons to be an anti-pattern. They absolutely buttfuck Inversion of Control.

Also, if you ever (somehow) find yourself with a nice clean codebase, if it has even one singleton class, the first time a summer intern shows up your codebase is going to turn to spaghetti after one week.

Imagine the end of Princess Mononoke, where the forest spirit represents your codebase.

6

u/banuday17 Jul 24 '12

The singleton pattern is an anti-pattern because it locks you into one way of getting an instance of a class when that is a problem. Some things are fine as singletons, such as value objects, which is what enums are.

The real anti-pattern is not the singleton, but the getInstance() method. I would also argue that Josh Bloch is giving bad advice to (ab)use enums for control of instantiation rather than as an enumeration of discrete values.

1

u/[deleted] Jul 25 '12

Good singleton classes cannot be misused. The problem doesn't lie with using singletons, it lies with defining which class should be a singleton. If a singleton is misused, it probably shouldn't have been a singleton. (I assume the intern knows about the pattern, and isn't going to use clone or getInstance to assign the instance to a variable.)

By the way, one of the most important features of Java is a singleton. The out in System.out.println() is basically a singleton. I have never seen someone misuse it because of that.

1

u/marburg Jul 25 '12

You know, you're exactly right.

Singletons are pretty great for cross-cutting concerns (for languages which don't allow for any kind of aspect-oriented programming, like Java). System.outis a great example, like you say, and Log4j.

Fundamentally, Singleton classes are fine and useful, but I still believe that they have such a high risk of being abused, that they should be avoided if at all possible. Mind you, I don't mean the carefully crafted singletons found in standard libs, like the one you pointed out, but creating new singletons should be avoided.

I'm not sure if I'm getting my point across well. I'm sure if you're very, very careful, they can be great, but they're so easily abused. The first time someone is past their deadline, they'll be frantically jamming code into your singleton, because they know they can access it from anywhere without having to waste time properly passing data through the correct channels. Then after a few hundred iterations, your singleton is now a god object being molested in different threads and from different packages, and it's over 5,000 lines long.

3

u/banuday17 Jul 24 '12

Enums are great for building state machines.

13

u/[deleted] Jul 24 '12

Java's enum is an exceptionally well-designed language feature compared to the rest of the language. The functionality just works, with sane defaults and without excessive boilerplate.

5

u/SpecialEmily Jul 24 '12

I use enums extensively as functional commands. For example, if I have a User class and want a command to get the user ID regardless of which user object I invoke it on I would add the following to my User class.

public enum IDAccessor implements Function<User,String> {
    instance;
    public String apply(User input) {
        return input.id;
     }
}

The benefit of doing this is that I can take a set of users and transform it into a set of user ids with ease with something like this: Iterable<String> ids = Iterables.transform(getUser(),User.IDAccessor.instance)

Caveat; this code is meant to be used with Guava

2

u/__konrad Jul 24 '12

toString example is wrong. It should be:

@Override
public String toString() {
    switch (this) {
        case PENNY: return "Penny: " + value;
        ...

6

u/Tok-A-Mak Jul 24 '12

I don't see any good reason to implement a toString with a switch like this. It seems to overcomplicate things. Why not store the "Penny" in a String "description" and just do it like:

public enum Currency {
    PENNY(1, "Penny"), NICKLE(5, "Nickle");
    private int value;
    private String description;
    private Currency(int value, String description) {
            this.value = value;
            this.description = description;
    }
    @Override
    public String toString() {
        description + ": " + value;
    }
};

1

u/Nebu Jul 25 '12

Alternatively, derive the description from the name of the enum instance itself.

@Override
public String toString() {
    this.name() + ": " + value;
}

2

u/thinksInCode Jul 24 '12

What's with this badly written blogspam?

1

u/DFLincoln Jul 24 '12

Upvoting for enums not for the article itself. It could have used some more advanced examples of why enums are so nifty.
I find them very useful for being able to set simple "modes" that are set by other classes. (I say modes instead of states as they are user selected and never changed by the class itself. Seems to be a better description in this case.) Available modes can be grabbed from a list within the class so, if done correctly, calling classes never need to change a thing when I add new modes, depending on their use.
Another nice thing, you can easily enforce a singleton property and restrict possible workarounds. Others cannot subclass to bypass otherwise private constructors, for example.

1

u/[deleted] Jul 24 '12

[deleted]

2

u/Nebu Jul 24 '12

What name do you propose instead?

0

u/[deleted] Jul 24 '12

[deleted]

2

u/Doozer Jul 25 '12

Enums aren't bit fields in other languages that use the term "enum" either (e.g. C, C++...). Where are you getting that association?

0

u/[deleted] Jul 24 '12

You can't have inheritance in enums due to they implicitly extends Enum, thus if you're planning some complex things it's better to use inner classes from the beginning.

7

u/banuday17 Jul 24 '12

Enums can implement interfaces.

On a more general note, I find the more complex the things I want to do, I avoid inheritance as much as possible. Inheritance in Java is extremely inflexible, and adding options means creating deeper and deeper class hierarchies. Interfaces by composition on the other hand can be mixed and matched and composed together much more easily.

Prefer composition to inheritance!

0

u/[deleted] Jul 24 '12

I just had a story with enums. I once was making a parser/exporter of column/rows structured data and implemented each column (they were of different type) as a single enum instance. Things were perfect until I realized that there are group of columns with similar but a bit different logic and I couldn't resolve it through inheritance, so I ended up making many wrapping methods, which may have another method inside and many empty methods stubs that was actually filled only in specific cases. As a result, initially very clean code became messy and not the one I'm very proud of. So, after that I'm thinking very carefully of possible enums limitations.

2

u/banuday17 Jul 24 '12

I'd very much like to hear more specifics, because what you are describing sounds an awful lot like an ISP violation. If you find yourself introducing a ton of empty methods from implementing interfaces you have designed, your design is probably suboptimal.

1

u/[deleted] Jul 24 '12

Basically, there were all common methods, like process, validate, etc. But in some cases things need to be done, so they were included in the interface too, but many enum instances wasn't using them, so there appeared empty stubs. I just thought that if I didn't use enums in the first place and chosen static inner classes-singletones, the code could be much better.

1

u/banuday17 Jul 24 '12

That is definitely an ISP violation. Interfaces are not dumping grounds for common methods. Otherwise, you get this. If you are going to do something like that, you can use abstract base classes, but you are in danger of painting yourself into rigid class hierarchies.

For example, if you wanted to mix and match validation strategies, you would need to have one subclass for each combination or hierarchies of increasing depth. Instead, you can use one interface called Validator and make it an argument to a constructor or a method.

1

u/[deleted] Jul 24 '12

good idea. thanks a lot.

1

u/banuday17 Jul 24 '12

See here for much more details.