• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

Java enum code structure

 
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello! When defining a class that requires and enum field, what is the best practice regarding code structure? Should I use an inner enum "class", and if so, what is the convention for placing this class? (eg before or after constructor etc)?

Thanks you in advance.

Toni
 
Saloon Keeper
Posts: 13282
292
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It all depends.

Regardless of whether it's an enum or a regular class, only nest them inside another class if their are very strongly related. For instance, in a game of Poker, you could have Suit and Rank enums nested inside a Card class. The identifiers Card.Suit and Card.Rank are very natural and make it clear that it's appropriate to nest the enums inside a class.

It's my personal preference to put "simple enums" (an enum that consists of only a handful of constants and nothing else) at the top of the class, after fields but before the constructor. I put a nested enum at the bottom of the enclosing class if the enum has a lot of constants, or declares fields or methods.
 
Marshal
Posts: 74054
332
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It isn't a convention about where you declare the enum tpe, but a design decision. If you declare the enum inside another class, it becomes a static nested type of that class, a member of that class.
If you declare it on its own it is a top‑level class. (Remember an enum is a special kind of class.)
That is why Stephan said only to declare the enum inside another type if the two are closely related.
 
Master Rancher
Posts: 4032
54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:It isn't a convention about where you declare the enum tpe, but a design decision.


Well, the decision about whether to make it as a nested class or not is a design decision.  But if you do make it nested, the decision about where to declare it within that class is not a design decision, but a convention.  And there is no standard convention, as far as I know.  Sun's ancient "Code Conventions for the Java TM Programming Language" kind of forgot to mention nested classes (the appropriate place would have been in this table, and was never updated for many other new language features. I don't think there's any particular convention that has come to dominate in the time since then.  So you're pretty much on your own, I think.  

My own preference seems to match Stephan's.  A very simple nested type can be up near the top, after variables and before constructors.  Otherwise it should be at the end.  When reading the top-level class, I don't want the reader distracted from the main purpose of the class.  So if the nested class is complex, move it out of the way.
 
Saloon Keeper
Posts: 24329
167
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:So if the nested class is complex, move it out of the way.



If a nested class is complex, it's likely it should be an independent class.
 
Antonio Moretti
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If it's nested it's a bit awkward to set an enum-type field with a constructor because you have to do [reference name].[enum name].[field name].
 
Mike Simmons
Master Rancher
Posts: 4032
54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:If a nested class is complex, it's likely it should be an independent class.


I generally agree.  But "complex" is relative - in the context of my previous comment, "complex" has a very low threshold in my mind.  At the beginning of a class, I don't want anything that takes more than a few lines, really -- I want to focus on the class.  Pretty much the only nested types I can think of that can be simple enough are enums, record classes, and occasional interfaces with very few methods that I don't feel the need to document extensively.  Even something like Map.Entry is complex enough that I would not want it in the front of the class declaration, but it still makes sense as part of the top-level interface Map.
 
Mike Simmons
Master Rancher
Posts: 4032
54
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Antonio Moretti wrote:If it's nested it's a bit awkward to set an enum-type field with a constructor because you have to do [reference name].[enum name].[field name].


I don't think so.  First, if you're inside the top-level class, then you can eliminate the outer reference name.  Second and more importantly, with nested types you can use simpler names for the parts of the name, knowing that it will be referred to by the combined name.  As an example, if Map.Entry had been made a top-level interface, it probably would have been called MapEntry.  Entry would be a rather poor name by itself, entry for what?  But as a nested type, Entry is fine, knowing it will be referenced in most places as a Map.Entry.  So, is Map.Entry a longer name than MapEntry?  Only by one character.  Doesn't seem like a problem, to me.  But of course, there would be no point in calling it a Map.MapEntry.  I think most nested type names can be similarly shortened to be very similar to the top-level names you would choose for them.
 
Antonio Moretti
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As a quick example, I have this Book class:


If I want to instantiate it from elsewhere:


I might be doing all this wrong though!

 
Mike Simmons
Master Rancher
Posts: 4032
54
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Good example.  If your enum is nested inside a Book, why call it BookType?  Why not just Type?  Then when you call it from elsewhere, it's a Book.Type.  Easy.

In other cases, if for some reason you can't shorten the name like that, you can also use static imports.  E.g.

lets you replace Book.BookType.BOTH with BookType.BOTH.  And

lets you replace it with BOTH.  Which may be too short, in some contexts.  But you can decide for yourself how much you want to shorten things, and how much context to provide.
 
Campbell Ritchie
Marshal
Posts: 74054
332
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Antonio Moretti wrote:. . . you have to do [reference name].[enum name].[field name]. . . .

You would usually use ClassName.NestedEnumName.fieldName because nested enums are implicitly static.
 
Antonio Moretti
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:You would usually use ClassName.NestedEnumName.fieldName because nested enums are implicitly static.


Aren't all enums static - or rather their fields?

 
Stephan van Hulst
Saloon Keeper
Posts: 13282
292
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Antonio Moretti wrote:Aren't all enums static


All nested enums are implicitly static. The static modifier doesn't apply to top-level enums.


or rather their fields?


No. Enum constants are static, but an enum may also have instance fields:

 
Antonio Moretti
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stephan, thanks. Very interesting but you lost me a bit there. What do you mean by a top level enum?

Also, why might we want an enum to have instance fields?
 
Stephan van Hulst
Saloon Keeper
Posts: 13282
292
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Antonio Moretti wrote:Stephan, thanks. Very interesting but you lost me a bit there. What do you mean by a top level enum?


A top level type is any type that is not nested in another type.

Also, why might we want an enum to have instance fields?


For the same reason a class has instance fields. An enum constant is just an object like any other, except that you have a fixed number of them.
 
Saloon Keeper
Posts: 1328
40
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Antonio Moretti wrote:
Also, why might we want an enum to have instance fields?


For the same reason a class has instance fields. An enum constant is just an object like any other, except that you have a fixed number of them.



Well, yes, except an enum can't sub-class any other class explicitly nor can itself be sub-classed.

Apart from inheritance, your enum can do anything a regular class can.

This is substantially enhanced from the earlier notion of enum in C or C++ which is just a fixed set of values, usually seen as an int.

As to an example, you could have a DayOfWeek enum, with a field of numberWorkHours which might be 0 for SUNDAY, 4 for SATURDAY and between 6 and 9 for the weekdays.

 
Campbell Ritchie
Marshal
Posts: 74054
332
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:. . . enum in C or C++ which is just a fixed set of values, usually seen as an int. . . .

More than enhanced; it is a completely new concept.

The Java™ Tutorials say,

Java programming language enum types are much more powerful than their counterparts in other languages. . . .

The original version added, “which are simply glorified integers.” Maybe somebody complained because the bit about glorified integers was removed from the tutorial page quite quickly.
 
Jesse Silverman
Saloon Keeper
Posts: 1328
40
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

The Java™ Tutorials say,

Java programming language enum types are much more powerful than their counterparts in other languages. . . .

The original version added, “which are simply glorified integers.” Maybe somebody complained because the bit about glorified integers was removed from the tutorial page quite quickly.



Also in C++, but even more in C, there were so many ways you could get bit in the butt by the fact that enums were just glorified integers that I don't feel it was at all unjustified.

enum is yet another example of where something came quite late to Java, yet the Java team learned from the mistakes of others who got the feature much earlier.

Annoying, because older code (some of which is still extant) had to improvise, but quite a bit nicer once you finally get it.

 
Campbell Ritchie
Marshal
Posts: 74054
332
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:. . . something came quite late to Java, yet the Java team learned from the mistakes of others . . .

It cuts both ways; I think when MS designed C#, they learnt from mistakes made with Java®.
 
Stephan van Hulst
Saloon Keeper
Posts: 13282
292
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Except they also remade old mistakes.

Don't get me wrong, I love C# and I think in many ways it's a better language than Java, but they really dropped the ball on enums, which once again are just glorified integers.
 
Campbell Ritchie
Marshal
Posts: 74054
332
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
They went one better in Eiffel; if I remember correctly, ECMA‑367 dropped the concept of enums altogether.
reply
    Bookmark Topic Watch Topic
  • New Topic