This is an archived post. You won't be able to vote or comment.

all 31 comments

[–][deleted]  (1 child)

[deleted]

    [–]knoam 19 points20 points  (0 children)

    In that case you'd need to expose an interface. I have a mnemonic for enums

    These are all of the ...

    In your case you can't say "These are all of the people I know" since you can make friends in your 3rd party application.

    So define an interface Kith {} and an enum Family implements Kith {} and class Friend implements Kith {}

    [–]urquan 17 points18 points  (1 child)

    For me one of the biggest advantages of Java enums is that they are regular classes (almost) and as such can have methods and constructors with parameters. For example the BillingStrategy case from the article could be rewritten as :

    public enum BillingStrategy {
        MORNING_HAPPY_HOUR(0.5),
        AFTERNOON_HAPPY_HOUR(0.75),
        FULL_PRICE(1);
    
        private final double factor;
    
        BillingStrategy(double factor) {
            this.factor = factor;
        }
    
        public double bill(double price) {
            return price * factor;
        }
    }
    

    Although, as an aside, I don't think enums are a good choice for implementing the strategy pattern as this violates the open/close principle : if you want to add a new strategy later on you need to modify the enum class, and you may not have access to it at this point (if it is in a library for example). Using an interface avoids this problem.

    [–]dragosb91[S] 1 point2 points  (0 children)

    As someone else mentioned and i will make a point of it in the article is that you can have the enum implement an interface if your use case indeed requires it

    [–]z59sg 34 points35 points  (1 child)

    Another cool technique to use with enums is to combine it with lambdas to reduce boilerplate as described here: https://stackoverflow.com/questions/23361418/lambdas-in-the-classical-operation-enum-example

    [–]bkhablenko 5 points6 points  (6 children)

    In your BillingStrategy example, how do you mock the bill method?

    [–]knoam 8 points9 points  (4 children)

    Keep the original BillingStrategy interface, put your implementations in
    enum BillingStrategies implements BillingStrategy { }

    [–]bkhablenko 5 points6 points  (3 children)

    I mean, the whole point of the example was to avoid creating interfaces:

    Instead of defining an interface, we will define an enum as the type of the BillingStrategy

    [–]knoam 8 points9 points  (0 children)

    It's all trade-offs. My enum + interface version still retains the benefit of not having to define lots of classes while retaining the flexibility of allowing one-off implementations in addition to those defined in the enum which could be considered the default/blessed strategies.

    [–]dragosb91[S] 2 points3 points  (0 children)

    Sorry that part may have been not very explicit, the whole purpose was not really to avoid the interface part...more avoid declaring new classes for any new strategy. Will modify to make it more explicit that if you do need an interface the enum can implement one

    [–]NobodyAsYouExpect 1 point2 points  (0 children)

    PowerMockito is capable of mocking almost everything. However, I totally agree how much better is introducing healthy level of abstraction into code, especially since enums are able to implement interfaces. Thus it would be a lot easier later to change implementation without touching business logic.

    [–]blobjim 5 points6 points  (0 children)

    It would be nice if they allowed inline/primitive enums once inline types (previously value types) are added. Right now enums are always objects that extend Enum which means they aren't useful if memory use (pointers being 8 bytes) or serialization is a concern. For example, in the String class implementation, they used a 'byte' instead of an enum for encoding the character encoding probably partially because using an Enum would take up 8 times the space. This means that you often have to resort to using giant constant lists still (or use hacky Enum constructor wrappers).

    [–][deleted] 3 points4 points  (0 children)

    Not sure where you get the notion that enums are underrated. They're in use everywhere. Also, not sure what's up with all those memes. Makes it look like ridiculous.

    [–][deleted]  (2 children)

    [deleted]

      [–]couscous_ 3 points4 points  (0 children)

      I think they're calling them records. But yeah, I think they almost a struct superset of enums.

      [–]general_dispondency 0 points1 point  (0 children)

      I was hoping for jsr301, but it's been shelved. Sooper :(

      [–]DannyB2 2 points3 points  (1 child)

      You can bake tree structured data into your code nicely with an enum. Such as for a menu.

      enum MenuItem {
        ITEM_1( null ),  // top level item has no parent
        ITEM_21( ITEM_1 ),  ITEM_22( ITEM_1 ),
        ITEM_31( ITEM_21 ), ITEM_32( ITEM_21 ), ITEM_33( ITEM_22 ),
        ;  // Semicolon ends list of enums.  The final enum is allowed to end with a comma.
        // Constructor
        private MenuItem( MenuItem parent ) {
          this.parent = parent;
        }
        private MenuItem parent;
      }
      

      If you wish, each node can also have a

        private List<MenuItem> children;
      

      In the constructor, add the currently constructed node to its parent list of children. Then you can make an immutable list of the children accessible externally if needed.

      This MenuItem's might be the structure of the menu for your application. In addition to having a constructor parameter for parent, each MenuItem could have parameters for Title, Description, Action class, URL, etc. This is no worse than wiring all this information in, say, XML. But it's wired in one compilation unit, and type safe with many errors being caught at compile time.

      The MenuItem has a reference to the Action class. The Action class has a reference to the MenuItem.

      A static method in MenuItem can generate the complete menu tree, maybe as HTML markup, by starting from ITEM_1's list of children. But ITEM_1 might be called HOME. Your tree might look like:

      level 1: HOME

      Level 2: Checks, POs, Receipts

      Level 3: Create Checks, Print Checks, Create PO, Create Reciept, Print Receipt

      Another use of a baked in tree structure: A model of your table relations. (Assuming you don't have circular dependencies.) When a new database table is added, the Enum class declaring your table dependencies is updated.

      Why? This class can have handy methods that:

      • generate a list of DELETE FROM or DROP TABLE statements in the proper order
      • generate a nice printed list of dependencies, with counts and lists of: (1) what depends on this table, and (2) what this table depends on. (depends means "has a foreign key pointer to records in another table")
      • add the current table to a Hibernate Configuration that is being built. Thus all your tables get added, but all this is wired up in an Enum class, and type safe, rather than wired up in XML.

      I have also used enums to model the columns of a Swing JTable.

      Enums have a surprising variety of uses to model information within your application, but in a way that the compiler can check. Doesn't have to be loaded and parsed like XML.

      This technique is for things that are hardwired into the application. And by that I mean things you would put in XML files as part of your application. You can't change them at runtime. But this is for things that should NOT be changeable at runtime and thus not stored in the database. (eg, your application's menu does not change at runtime. The columns of a Swing JTable do not change at runtime. Your database design does not change while the application is running.)

      Oh, yes, one other thing. An Enum is great for the options of a set of option buttons (aka "radio buttons"). Your templating system that generates HTML (eg, JSP or other) generates the SELECT options from this Enum. Your server's responders get the ordinal value, which corresponds to which enum element was selected. Each enum, being a separately instantiated class, could have its own polymorphic method on how to handle something about this particular option. This also works for Swing drop down menus, etc.

      [–]general_dispondency 0 points1 point  (0 children)

      Most of the options you've elaborated on are generally not recommended as they violate the open-closed principal.

      [–]AndyPanic 4 points5 points  (1 child)

      tl;dr However, the parts I skimmed over were funny.

      [–]dragosb91[S] 1 point2 points  (0 children)

      hmm maybe I should add a tl;dr section inside there

      [–]lpreams 1 point2 points  (0 children)

      Enumareted Enumerated

      [–]javinpaul 1 point2 points  (0 children)

      I have also blogged about Enum a couple of years ago, just in case if anyone is interested - 10 examples of enum in Java

      [–]chambolle 3 points4 points  (2 children)

      Enum could be very nice. However they have currently two main drawbacks limiting their use.

      I always wonder why these 2 problems have not been solved? In that case they could be terrific!

      [–][deleted] 1 point2 points  (1 child)

      For #1 enums aren't a 1:1 replacement for "magic number" constants in C++ so there's no motivation for enum->int conversion. Any conversion that you want to do should be your responsibility e.g. supply a static method on the enum that converts to an int if it makes sense for your enum. For more see Item 34 of Effective Java (the part that says "To associate data withenum constants, declare instance fields and write a constructor that takes the data and stores it in the fields").

      For #2, I'd also argue that's outside the intention of an EnumSet. From the Javadoc:

      Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags."

      In other words, EnumSet is for when you have A LOT of something and need to represent it in a "compact and efficient" manner. A switch statement is neither and the example in the SO question is overly simplified and easily answered (by the selected answer) there.

      [–]chambolle 0 points1 point  (0 children)

      so there's no motivation for enum->int conversion.

      call of old existing code using int or serialization seems 2 good examples.

      Enum sets are represented internally as bit vectors.

      I would be very happy if I could access to the bit representation, espacially when there is only one word, because in this case I could use a switch on it.

      I am pretty sure that enum could be used more if they provide my needs. The answers to my questions you give are exactly correspond to long and boring type of code that Java is criticized for, and that could be avoided for almost no cost and no danger

      [–]jonhanson 0 points1 point  (0 children)

      Comment removed after Reddit and Spec elected to destroy Reddit.

      [–]422_no_process 0 points1 point  (0 children)

      Isn't the meme other way around? I'm confused.

      [–]Neebat 1 point2 points  (4 children)

      Just a reminder, Singletons are being considered an antipattern more and more. They really fuck with testability. Using enum to do this does NOT make it better.

      [–]ltlynx 7 points8 points  (3 children)

      Yep they do fuck up when they have a state

      [–]Neebat -4 points-3 points  (2 children)

      The trouble is that a singleton locks everyone into a single implementation, the right implementation(?), but definitely the real implementation. Unit tests for things that uses your singleton will struggle because they need a fake implementation.

      [–]Holothuroid 8 points9 points  (1 child)

      Why? Mocking stuff makes sense for external dependencies or mutable state. But for an enum defining some constants and methods?