Java Forum / General / July 2007
masks and enums
Wojtek - 24 Jul 2007 00:22 GMT If I have a mask set:
public static final long MASK_NONE = 0x000; public static final long MASK_ONE = 0x001; public static final long MASK_TWO = 0x002; public static final long MASK_THREE = 0x004; public static final long MASK_FOUR = 0x008; public static final long MASK_FIVE = 0x010;
I can quite easily use them together:
MASK_ONE | MASK_FOUR
However as a constructor/method parameter I am passing in a long. I would like to use an enum:
public enum Mask { NONE, ONE, TWO, THREE, FOUR, FIVE; }
However the spec does not allow concatination of enums. To get around this I can: 1. use a variable number of parameters 2. use an array of enums 3. use an object which contains a list (map) of the enums. However this is as bad as having a complete set of isMaskX/setMaskX for each mask type in some object. 4. list every possible combination of enums as their own enum. However this expands really quickly and adding a new enum would be a royal pain. 5. throw up my hands in disgust and keep using the longs 6. some other elegant solution?
 Signature Wojtek :-)
Patricia Shanahan - 24 Jul 2007 00:28 GMT > If I have a mask set: > [quoted text clipped - 28 lines] > 5. throw up my hands in disgust and keep using the longs > 6. some other elegant solution? 7. use java.util.EnumSet.
Patricia
Wojtek - 24 Jul 2007 00:32 GMT Patricia Shanahan wrote :
> 7. use java.util.EnumSet. > > Patricia I REALLY need to take some time and take an upgrade course....
 Signature Wojtek :-)
Roedy Green - 24 Jul 2007 02:49 GMT >I can quite easily use them together: > >MASK_ONE | MASK_FOUR see http://mindprod.com/jgloss/enumset.html
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Wojtek - 24 Jul 2007 16:28 GMT Roedy Green wrote :
>> I can quite easily use them together: >> >> MASK_ONE | MASK_FOUR > > see http://mindprod.com/jgloss/enumset.html I did. Your site popped at nearly the top of a Google search (oh the fame.... :-).
You might want to add that enumSet.contains(MyEnum.MASK) replaces a standard bit comparison. I know it is part of the Collection classes, but it could be highlighted.
 Signature Wojtek :-)
Roedy Green - 29 Jul 2007 17:06 GMT >You might want to add that enumSet.contains(MyEnum.MASK) replaces a >standard bit comparison. I know it is part of the Collection classes, >but it could be highlighted. contains expects an Object but the docs have nothing to say about the type that object. What is this MASK? another EnumSet? a Long?
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Roedy Green - 29 Jul 2007 17:30 GMT >You might want to add that enumSet.contains(MyEnum.MASK) replaces a >standard bit comparison. I know it is part of the Collection classes, >but it could be highlighted. I have updated the entry and written a new piece of sample code. See if I covered everything you think is important. see http://mindprod.com/jgloss/enumset.html
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Wojtek - 30 Jul 2007 16:30 GMT Roedy Green wrote :
>> You might want to add that enumSet.contains(MyEnum.MASK) replaces a >> standard bit comparison. I know it is part of the Collection classes, >> but it could be highlighted. > I have updated the entry and written a new piece of sample code. See > if I covered everything you think is important. > see http://mindprod.com/jgloss/enumset.html Yes, it is much clearer now as to how to use EnumSet.
I am curious about this statement: "Normally it would be public in its own *.java file".
I usually place the enum on the class which uses it:
-------------------------------------- public Class Foo { public enum CompareType { TEXTUAL, NUMERIC; }
....
public boolean fooCompare(String value, CompareType compare ) {
if ( compare == NUMERIC ) // code to do a compare on 'value' after converting it to a number else // code to compare two strings } --------------------------------------
To me it makes more sense to place the enum within this class rather than creating a separate class which only holds the enum. Or worse a class which only holds all the enums for a project.
And since everything has an exception, I do place certain enums in a singleton which holds application wide "magic numbers".
 Signature Wojtek :-)
Roedy Green - 30 Jul 2007 16:50 GMT >I am curious about this statement: "Normally it would be public in its >own *.java file". > >I usually place the enum on the class which uses it: 1. I though there was a limit of one public class per *.java file.
2. I like to put one class per *.java file because it makes classes easier to find.
3. It seems to me, the compiler would have troubles finding the source for classes if you don't do that, but obviously it somehow does.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Steve Wampler - 30 Jul 2007 17:24 GMT >> I am curious about this statement: "Normally it would be public in its >> own *.java file". >> >> I usually place the enum on the class which uses it: > > 1. I though there was a limit of one public class per *.java file. I think that's right, also. My best guess is that 'public enum' is indeed a different entity than 'public class' and so operates under different rules.
I'm not sure I like this, if true. I would have expected references to an 'embedded' enum to behave like other class entities. That is, references for:
public class Foo { public enum CompareType {
would have needed to be qualified as Foo.CompareType, ala inner classes. Not that it really matters, since it's a done deed, apparently.
 Signature Steve Wampler -- swampler@noao.edu The gods that smiled on your birth are now laughing out loud.
Wojtek - 30 Jul 2007 19:42 GMT Steve Wampler wrote :
>>> I am curious about this statement: "Normally it would be public in its own >>> *.java file". [quoted text clipped - 16 lines] > would have needed to be qualified as Foo.CompareType, ala inner classes. > Not that it really matters, since it's a done deed, apparently. You do need to use Foo.CompareType ala inner classes. Unless, of course, you are within the enclosing class.
Except in switch/case, where you can ONLY use the enums within the CompareType. No qualification allowed.
 Signature Wojtek :-)
Lew - 30 Jul 2007 20:06 GMT >>> I am curious about this statement: "Normally it would be public in >>> its own *.java file". >>> >>> I usually place the enum on the class which uses it: >> >> 1. I though there was a limit of one public class per *.java file. Nested classes can be public.
> I think that's right, also. My best guess is that 'public enum' is > indeed a different entity than 'public class' and so operates under > different rules. The OP nested his enum.
> I'm not sure I like this, if true. I would have expected references > to an 'embedded' enum to behave like other class entities. That is, [quoted text clipped - 4 lines] > > would have needed to be qualified as Foo.CompareType, ala inner classes. That's the syntax for non-inner nested classes, not for inner classes. Inner classes need an enclosing instance, e.g., "new Foo().CompareType".
> Not that it really matters, since it's a done deed, apparently. Inner classes don't have to be qualified by the enclosing instance when referred to from the enclosing instance.
Which begs the question of why this particular inner enum is public in the first place.
The OP's philosophy of always making such enums inner (why not static nested?) is certainly open to debate. Endless debate, perhaps - the use of inner classes generally is a black art and controversial to some.
 Signature Lew
Wojtek - 30 Jul 2007 22:39 GMT Lew wrote :
> Which begs the question of why this particular inner enum is public in the > first place. Some are public, some are private, some are package level. Depends on the circumstances and who needs to use it.
> The OP's philosophy of always making such enums inner (why not static > nested?) is certainly open to debate. Endless debate, perhaps - the use of > inner classes generally is a black art and controversial to some. As I understand it:
public enum
is the same as:
public static enum
 Signature Wojtek :-)
Daniel Pitts - 31 Jul 2007 01:30 GMT > Lew wrote : > [quoted text clipped - 18 lines] > -- > Wojtek :-) Lew, enums are always "static".
I don't have a hard and fast rule about where I put my enums. Sometimes they make since on there own, and sometimes they only make since as "part of" another class. I tend to put them in the first class that uses them, and then refactor them to package level if it seems appropriate.
Lew - 31 Jul 2007 02:23 GMT >> Lew wrote : >> [quoted text clipped - 24 lines] > class that uses them, and then refactor them to package level if it > seems appropriate. Right, good point. But the question still stands as to why they must be nested, or when it might be better. That's the black art.
 Signature Lew
Twisted - 31 Jul 2007 02:33 GMT > Right, good point. But the question still stands as to why they must be > nested, or when it might be better. That's the black art. Eh. Isn't it fairly simple?
public class Widget extends JComponent { public static enum Alignment {LEFT, RIGHT, CENTER}; ... }
when only one class tree, Widget and descendants, uses the alignment, and
public enum WidgetAlignmemt {LEFT, RIGHT, CENTER}
when lots of independent FooWidgets occur that have an alignment of this sort, and there's no compelling type-safety reason to treat each type's alignment options as a separate type.
In particular, if FooWidget might add new alignment options in the future irrelevant to the others it should use its own nested enum, so we can add TOP_LEFT, TOP, TOP_RIGHT, BOTTOM_LEFT, BOTTOM, and BOTTOM_RIGHT when it has two degrees of freedom someday without all the others that are just aligning text needing to now detect bogus values like TOP_LEFT and throw exceptions, or translate them to use only the horizontal part.
Of course that might be done by instead having a VAlignment {TOP, BOTTOM, CENTER} enum and modifying FooWidget to use one of each, too. But it's not always so orthogonally decomposable...
If you mean more general with nested and inner classes, ordinarily you nest only when the would-be nested class is only used together with (a subclass of) the would-be nesting class rather than having independent use, and you make an inner class only when it's something that it makes sense to tie to an instance, such as iterators viewing a particular collection instance.
Roedy Green - 31 Jul 2007 12:50 GMT >Right, good point. But the question still stands as to why they must be >nested, or when it might be better. You might nest them if they are used by only the enclosing class. I find though the enums tend to be popular and reused elsewhere, so I tend to put them in a separate public or default class in their own file.
Also too, I tend now to put more and more logic in the enums, and less in the classes that use them. It makes sense then to give them their own file to grow in.
But the main reason is I can find them more easily then they are in their own file.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Daniel Pitts - 31 Jul 2007 16:09 GMT On Jul 31, 4:50 am, Roedy Green <see_webs...@mindprod.com.invalid> wrote:
> >Right, good point. But the question still stands as to why they must be > >nested, or when it might be better. [quoted text clipped - 7 lines] > in the classes that use them. It makes sense then to give them their > own file to grow in. I tend to do this too. If there is behavior the should be executed based on the enum value, I add it to the enum itself, and then just call myEnumValue.foo(); :-)
Who'd have thought that enums and polymorphism could be mixed. As well as being singletons.
> But the main reason is I can find them more easily then they are in > their own file. > -- > Roedy Green Canadian Mind Products > The Java Glossaryhttp://mindprod.com Wojtek - 31 Jul 2007 16:38 GMT Roedy Green wrote :
>> Right, good point. But the question still stands as to why they must be >> nested, or when it might be better. [quoted text clipped - 10 lines] > But the main reason is I can find them more easily then they are in > their own file. Hmmm, I prefer to put them in the class which uses them. Rarely do I use an enum without also using the owning class' methods.
That way I do not need to get creative with class names. So rather than having:
FooEnum.Bar.OPTION which is used in Foo
I have
Foo.Bar.OPTION
And I always put the enum at the top of the class code. With Eclipse, I have enums coloured differently so they are easy to spot in the source code. And getting to the enum is a CTRL-Click away.
Just had a thought. Do you import right the enum? I only import to the owning class, then use <class>.<enum> to use it. It sort of reads like a sentence that way, plus I can see the owning class.
 Signature Wojtek :-)
Wojtek - 30 Jul 2007 18:51 GMT Roedy Green wrote :
>> I am curious about this statement: "Normally it would be public in its >> own *.java file". [quoted text clipped - 8 lines] > 3. It seems to me, the compiler would have troubles finding the source > for classes if you don't do that, but obviously it somehow does. But an enum is not really a "full" class. You cannot extend it for instance.
I also only put one class per file, except where it makes more sense, such as a private class only used within the enclosing class.
I do use somewhat deeply nested public classes in things like constants where I organize information:
public class Foo { public static final String VALUE = "value";
public static class Bar { public static final String VALUE = "barValue"; } }
which can be accessed as:
Foo.Bar.VALUE
 Signature Wojtek :-)
Daniel Pitts - 31 Jul 2007 01:32 GMT > Roedy Green wrote : > [quoted text clipped - 37 lines] > -- > Wojtek :-) The the time you have nested constants, you might look into using an external configuration, such as Properties, or a custom XML file. Or, possibly using Dependency Injection.
Wojtek - 31 Jul 2007 02:03 GMT Daniel Pitts wrote :
> The the time you have nested constants, you might look into using an > external configuration, such as Properties, or a custom XML file. Or, > possibly using Dependency Injection. So I lied a little :-)
public class Lang { public class Report { public class Finance { public static final LangKey HEAD_TOTAL = new LangKey("report.finance.head.total"); } } }
Used as: Lang.Report.Finance.HEAD_TOTAL
Which is used in my custom made I18N class. That way ONLY a LangKey can be passed as a language key, which makes sure that a typo does not occur. Or rather, that a typo can only be made in one place.
I do use properties, but then the keys for the properties are also nested constants.
I really HATE magic numbers...
 Signature Wojtek :-)
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|