Enums

  • Stand for enumeration meaning “specifically listed”
  • enum is just like class except that enum constants are public, static, final and cannot be overridden
  • All enum constructor should be private and hence It cannot be used to create objects
  • All enums implicitly extends java.lang.Enum and hence cannot extend any other class
  • All enums implicitly implements Serializable and Comparable and it can implement other interfaces
  • An enum cannot be extended by other class, It is implicitly final or implicitly sealed

Constructor

  • It is implicitly private
  • You can only specify private access modifier explicitly.
  • You cannot invoke an enum constructor yourself.

Constants

  • enum constants are public, static, final and cannot be overridden
  • No explicit modifier is allowed for enum constants
  • Since constants are static, All enum instances are created by the JVM in the same way as Static Fields of a class, like running static initializers
  • Java requires that the constants be defined first, prior to any fields or methods.
  • When there are fields and methods, the list of enum constants must end with a semicolon.
enum Direction {
    NORTH,
    EAST,
    WEST,
    SOUTH; // Semi-colon is not mandatory, since we don't have fields/methods
}

Fields

  • Normal accessibility access rules apply.
  • Since you cannot subclass, hence protected works same as package-private
  • Rare condition:
    • It is a compile-time error to reference a static field of an enum type from:
      • constructors
      • instance initializers, or instance variable initializer
    • This restriction is not on constants

Methods

  • Normal accessibility access rules apply.
  • By default following static methods are provided:
    • values(): static method to return array of enum values
    • valueOf(): static method to create an enum object from name in string
  • By default following non-static methods are provided:
    • name(): The exact name as defined in the enum constant.
    • ordinal(): (avoid usage) The index as the enum constant appear.
      • Designed for use by sophisticated data structures EnumSet, EnumMap
    • compareTo(): use ordinal value and performs comparison by calculating their difference
    • toString(): By default enum constant name in string
  • It can have static methods
  • If you create an abstract method in enum then all enum fields must implement it
  • Since enum constants are final, they can be safely compared with both equals() and ==
enum CardType {
    SILVER("gray"),
    GOLD("yellow") {
        // This will override the toString method of the enum
        // We can also override other methods if needed
        @Override
        public String toString() {
            return "Gold Card has " + getColor() + " color!";
        }
    },
    PLATINUM("black"); // semicolon after defining all constants
 
    private final String color; // color of the card
 
    // the constructor is private and automatically called
    // on the above enum constants
    private CardType(String color) {
        this.color = color;
    }
    public String getColor() { return color; }
}
 
public class Test {
    public static void main(String[] args) {
        System.out.println(CardType.GOLD.getColor()); // yellow
        System.out.println(CardType.GOLD.name()); // GOLD
        System.out.println(CardType.GOLD.ordinal()); // 1
 
        // calls toString() internally
        System.out.println(CardType.GOLD); // [Overridden] Gold has yellow color!
        System.out.println(CardType.PLATINUM); // [Default] PLATINUM
 
        // static methods
        System.out.println(CardType.valueOf("SILVER").getColor()); // gray
        System.out.println(CardType.values()[0].getColor()); // gray
 
        // comparison
        System.out.println(CardType.GOLD.compareTo(CardType.SILVER)); // 1
        System.out.println(CardType.GOLD.compareTo(CardType.PLATINUM)); // -1
    }
}
  • It is possible to have main() method on enum
enum Rank {
    FIRST(20), SECOND(0), THIRD(8);
    Rank(int value) {
        System.out.print(value);
    } 
 
    public static void main(String[] args) {
        System.out.println(" " + Rank.values().length);
        // 2008 3
    }
}

Converting between different enums

  • Use switch statement
  • If name matches then valueOf() with name() can be used:
    • Be careful, if the name does not match then IllegalArgumentException is thrown at runtime
enum OrderStatus {
    ACTIVE,
    PENDING;
}
 
enum CmsOrderStatus {
    ACTIVE,
    PENDING;
}
 
public class Test {
    public static void main(String[] args) {
        System.out.println(CmsOrderStatus.valueOf(OrderStatus.PENDING.name())); // PENDING
    }
}