|  | Enums | 
 | 
This pattern has many problems, such as:// int Enum Pattern - has severe problems! public static final int SEASON_WINTER = 0; public static final int SEASON_SPRING = 1; public static final int SEASON_SUMMER = 2; public static final int SEASON_FALL = 3;
int
        you can pass in any other int value where a season is
        required, or add two seasons together (which makes no sense). SEASON_) to avoid
        collisions with other int enum types. In Java 5.0, the Java programming language gets linguistic support for enumerated types. In their simplest form, these enums look just like their C, C++, and C# counterparts:
      enum Season { WINTER, SPRING, SUMMER, FALL }
    
    But appearances can be deceiving. Java programming language enums
      are far more powerful than their counterparts in other languages,
      which are little more than glorified integers. The new enum
      declaration defines a full-fledged class (dubbed an enum type).
      In addition to solving all the problems mentioned above, it allows
      you to add arbitrary methods and fields to an enum type, to
      implement arbitrary interfaces, and more. Enum types provide
      high-quality implementations of all the Object methods.
      They are Comparable and Serializable, and the
      serial form is designed to withstand arbitrary changes in the enum
      type. 
Here is an example of a playing card class built atop a couple of
      simple enum types. The Card class is immutable, and
      only one instance of each Card is created, so it
      need not override equals or hashCode:
    
  import java.util.*;
          
          /** A standard playing card with a rank and a suit. Card is
          immutable. */
          public class Card
          {
              public enum Rank
                {
                    DEUCE, THREE,
            FOUR, FIVE, SIX,
                    SEVEN, EIGHT,
            NINE, TEN, JACK, QUEEN, KING, ACE
                }
                
                public enum Suit
                {
                    CLUBS, DIAMONDS,
            HEARTS, SPADES
                }
               
              public final Rank rank;   
              public final Suit suit;
              
              /** Construct a card from its rank and suit
          */
              public Card (Rank rank, Suit suit)
              {
                  this.rank = rank;
                  this.suit = suit;
              }
                 
              /** Return a printable representation of
          this card */
              public String toString ()
              {
                  return rank + " of
          " + suit;
              }
          }
          
          
         
     The toString method for Card
      takes advantage of the toString methods for Rank
      and Suit. Note that the Card class is
      short (about 12 lines of code). If the typesafe enums (Rank
      and Suit) had been built by hand, each of them would
      have been significantly longer than the entire Card
      class.
      The constructor of Card takes two parameters, a Rank
        and a Suit. If you accidentally invoke the
        constructor with the parameters reversed, the compiler will
        politely inform you of your error. Contrast this to the int
        enum pattern, in which the compiler wouldn't see any error and
        instead the program would fail at run time. 
Note that each enum type has a static values()
        method that returns an array containing all of the values of the
        enum type in the order they are declared. This method is
        commonly used in combination with the for-each
        loop to iterate over the values of an enumerated type.
    
Note also that each enum type has a static valueOf()
      method that returns the enum instance given its string
      representation.  Thus,    Rank.valueOf("TEN");
      returns Rank.TEN.
    
The following example is a client class called Deck
      that exercises Card. It reads two numbers from the
      command line, representing the number of hands to deal and the
      number of cards per hand. Then it creates a new deck of cards,
      shuffles it, and deals and prints the requested hands. 
import java.util.*;
public class Deck
{
private static final List<Card> protoDeck = new ArrayList<Card>();
private List<Card> deck = new ArrayList<Card>();
// Static initializer for a prototype deck
static
{
for (Card.Suit suit : Card.Suit.values())
{
for (Card.Rank rank : Card.Rank.values())
{
protoDeck.add(new Card(rank, suit));
}
}
}
/** Construct a deck from the prototype */
public Deck()
{
deck = new ArrayList<Card>(protoDeck); // create a copy of prototype deck
}
/** Shuffle the cards in the deck */
public void shuffle()
{
Collections.shuffle(deck);
}
/** Deal a hand of cards with the given number of cards.
* @param cardsPerHand desired cards in the dealt hand
*/
public List<Card> dealHand(int cardsPerHand)
{
int deckSize = deck.size();
List<Card> handView = deck.subList(deckSize-cardsPerHand, deckSize);
ArrayList<Card> hand = new ArrayList<Card>(handView);
handView.clear();
return hand;
}
/** Deal a few hands to demonstrate Deck.
* @param args The first argument is an integer for the desired number of hands,
* the second is the number of cards in each hand.
*/
public static void main(String args[])
{
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);
Deck deck = new Deck();
deck.shuffle();
// Iterate desired number of hands
for (int hand=0; hand < numHands; hand++)
{
System.out.println(deck.dealHand(cardsPerHand));
}
}
}
$ java Deal 4 5 [FOUR of HEARTS, NINE of DIAMONDS, QUEEN of SPADES, ACE of SPADES, NINE of SPADES] [DEUCE of HEARTS, EIGHT of SPADES, JACK of DIAMONDS, TEN of CLUBS, SEVEN of SPADES] [FIVE of HEARTS, FOUR of DIAMONDS, SIX of DIAMONDS, NINE of CLUBS, JACK of CLUBS] [SEVEN of HEARTS, SIX of CLUBS, DEUCE of DIAMONDS, THREE of SPADES, EIGHT of CLUBS]
Suppose you want to add data and behavior to an enum. For example consider the planets of the solar system. Each planet knows its mass and radius, and can calculate its surface gravity and the weight of an object on the planet. Here is how it looks:
public enum Planet
{ MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7), PLUTO (1.27e+22, 1.137e6); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius)
{ this.mass = mass; this.radius = radius; } public double mass() { return mass; } public double radius() { return radius; } // universal gravitational constant (m3 kg-1 s-2) public static final double G = 6.67300E-11; public double surfaceGravity()
{ return G * mass / (radius * radius); } public double surfaceWeight(double otherMass)
{ return otherMass * surfaceGravity(); } }
The enum type Planet contains a constructor, and
      each enum constant is declared with parameters to be passed to the
      constructor when it is created. 
Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):
public static void main(String[] args)
{ double earthWeight = Double.parseDouble(args[0]); double mass = earthWeight/EARTH.surfaceGravity(); for (Planet p : Planet.values())
{
System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass));
}
}
$ java Planet 175 Your weight on MERCURY is 66.107583 Your weight on VENUS is 158.374842 Your weight on EARTH is 175.000000 Your weight on MARS is 66.279007 Your weight on JUPITER is 442.847567 Your weight on SATURN is 186.552719 Your weight on URANUS is 158.397260 Your weight on NEPTUNE is 199.207413 Your weight on PLUTO is 11.703031
| Modifed from the original |  |