Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have this weird scenario in which some Java property is used to build and HQL query, and the type of the field is Boolean, i.e. it is boxed. I wondered why because I don't really like to think of booleans as having three possible values, true, false, and null. I recently found out the null value actually has semantics in this system. The semantics are: true means "only unviewed", false means "only viewed", and null means "all". So, if null, the field is ignored when building the HQL query, so that the end result contains both unviewed and viewed results.

In my opinion this is a case where an enum should be used. Something like this:

enum ViewStatus {
  VIEWED, UNVIEWED;
}

My dilemma now is what to use for the third case that should represent the union of these two constants? The two options are:

  1. Introduce a third enum constant, ALL.

    enum ViewStatus {
      VIEWED, UNVIEWED, ALL;
    }
    
  2. Use an EnumSet.

EnumSet pretty much exists specifically for this purpose, but... it seems like just two much overhead. Especially when reading the values in the part of the code that builds the HQL.

So, what are your thoughts? Shall I go with a third enum constant and refactor to EnumSet when need arises?

Thanks!

Update

I'll go for an EnumSet because I want to introduce methods on that enum that wouldn't make sense to be called on ALL. For example ViewStatus.isViewed().

share|improve this question
1  
This is a design question and therefore on topic for Programmers. –  ChrisF Aug 30 '11 at 14:05
1  
Tri-state boolean: TRUE, FALSE, FILE_NOT_FOUND :) –  Wayne M Aug 30 '11 at 17:22
    
Actually, while the OP is asking about design, this question is concerned more with the efficiency and language details. –  maaartinus Sep 1 '11 at 7:34
    
@maaartinus, I wasn't interested in efficiency of the code, but more in the developer comprehension overhead, and separation of responsibilities. As I said in my update, I went with an EnumSet, even if the comprehension radius is a bit greater, just because I had to put methods on that enum that would trigger WTFs if called on the ALL constant. –  Ionuț G. Stan Sep 1 '11 at 7:43
    
@Ionuț G. Stan: OK, then ignore the corresponding part of my answer. –  maaartinus Sep 1 '11 at 8:05

2 Answers 2

In this situation I use this pattern :

public class ViewStatusTest {
    public final static class ViewStatus {
        public static final ViewStatus FALSE = new ViewStatus();
        public static final ViewStatus TRUE = new ViewStatus();
        public static final ViewStatus ALL = new ViewStatus();
        private ViewStatus() {
        }
    }
/** @param args */ public static void main(final String[] args) { final ViewStatus vs = ViewStatus.TRUE; if(ViewStatus.FALSE == vs) { System.out.println("FALSE"); } else if(ViewStatus.TRUE == vs) { System.out.println("TRUE"); } else { System.out.println("ALL"); } } }

It is optimised because it test on internal address (not to necessary to load object and look inside).
In hope it will be usefull for HQL.
Best regards

share|improve this answer
2  
You're just implementing an enum manually as everybody had to before Java 5. It works fine but offers no single advantage when compared to an enum (you really should also implement toString and maybe other methods like compareTo or ordinal). –  maaartinus Sep 1 '11 at 7:31

I rather avoid things like

ViewStatus viewStatus;

since it introduces a new class without giving you anything in return when compared to

boolean isViewed;

But that's a matter of personal taste.


By setting the reference to null you can have a third value, which is not really good, since you can get an unexpected NPEsomewhere; null is just no "first class value".

EnumSet pretty much exists specifically for this purpose, but... it seems like just two much overhead. Especially when reading the values in the part of the code that builds the HQL.

The overhead of an EnumSet is reasonable, it caches the class and an array of all values, and uses a long for storing the data (as long as the enum is small enought). Its equals method is quite fast, but obviously slower than reference comparison. You mentioned using HQL, so most probably the runtime will be dominated by the database access, so IMHO you're needless and premature optimization.

The mutability of the EnumSet may be a problem sometimes, but there's ImmutableEnumSet in guava.


I'll go for an EnumSet because I want to introduce methods on that enum that wouldn't make sense to be called on ALL. For example ViewStatus.isViewed().

I don't think you stated all your alternatives right. You can have both

enum ViewStatus {VIEWED, UNVIEWED}

and

enum ViewStatuses {VIEWED, UNVIEWED, ALL}

where the second is an replacement for the EnumSet. That said, I agree with your decision.

share|improve this answer
    
Hm, actually, I think your last suggestion makes quite a lot of sense. I'll sleep a bit on the idea of dropping the EnumSet and introduce a second enum. The logic would be that the first enum applies to individual entities, while the second applies to collection of entities. –  Ionuț G. Stan Sep 1 '11 at 8:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.