Enum

Enum

Enum in Java

Written by: saeed1907057

Sun, 17 Nov 2024

Introduction

  • enum is a special data type that is mainly used for defining constant.
  • For example: for an attendance system, we can define an enum AttendType, having two constants named PRESENT, ABSENT.

Why do we need it?

  • It provides a clear and type safe way to define constants.
  • Increases code readability and prevent unexpected bugs.
  • We can use simple string or other type instead of enum as well, to make our job done. But problem is:
    • With string or other type, it is easy to make mistake. For example: instead of PRESENT, if we type present, then it may create bug.
    • Enum makes code more readable. We can easily check different type of attendance type just by looking at the AttendType enum.
    • We can add extra functionality to an enum. For example: we can use an integer id for each enum, which can be used for storing in database. But we can continue operation by name.

Structure of an enum

  • Simple format for declaring an enum is as follows:
    <access-modifier> enum <enum-type-name> {
        // List of comma separated names of enum constants, and functions if needed
    }
    
  • For example:
    public enum Gender {
        MALE, FEMALE; // all others genders are invalid
    }
    

Good to know

  • Use CamelCase for enum name. Ex: Gender.
  • Use uppercase for each enum constant. Ex: MALE, FEMALE.
  • Java implements the enum as class, but it(compiler) does a lot of work internally.
  • We can't create object of enum type. But enum can have constructor, used by the compiler only. The constructors of enum become private by default by compiler.
  • It can be used in switch statement as well.
  • We can define enum inside class, interface, or another enum.

Enum with extra properties

  • Let's see an example first:
    public enum MyWeekDay {
        SATURDAY(true),SUNDAY(false),MONDAY(false),
        TUESDAY(false), WEDNESDAY(false),THURSDAY(false), FRIDAY(false);
    
        // see above constant carefully. They all are objects. 
        // We are actually using constructor of this class to create constant.
    
        private final boolean isHoliday;
        private MyWeekDay(boolean isHoliday){ // it will be made private even if we use public or protected
            this.isHoliday = isHoliday;
        }
    
        public boolean isHoliday() {
            return isHoliday;
        }
    
    }
    
  • Example usage of the enum:
    private static int countWorkingDays(List<MyWeekDay> days){
        int counter = 0;
    
        for(MyWeekDay day : days){
            if(day.isHoliday()) continue;
    
            counter++;
        }
    
        return counter;
    }
    
    ArrayList<MyWeekDay> days = new ArrayList<>();
    days.add(SATURDAY);
    days.add(MONDAY);
    days.add(THURSDAY);
    
    System.out.println(countWorkingDays(days)); // 2
    

Comparing enum constant

Before going to comparison, let's us understand ordinal first.

  • An integer order number is assigned to each enum constant called ordinal.

  • The ordinal starts with zero & it is incremented by one for enum constant.

  • Ex:(See Gender enum).

    System.out.println(Gender.MALE.ordinal());   // 0
    System.out.println(Gender.FEMALE.ordinal()); // 1
    
  • Two enum constants can be compared in 3 ways:

    • compareTo() method:
      • Return the difference between their ordinal. 0 means same enum constants
      • Must be of same type.
      • Example:
        System.out.println( Gender.MALE.compareTo(Gender.FEMALE) ); // -1
        System.out.println( Gender.FEMALE.compareTo(Gender.FEMALE) ); // 0
        // System.out.println( Gender.FEMALE.compareTo(AttendType.ABSENT) ); // compile error
        
    • equals() method:
      • Return true if same enum constant, else false.
      • Different types of enum constants can be compared.
      • Example:
        System.out.println( Gender.MALE.equals(Gender.FEMALE) ); // false
        System.out.println( Gender.FEMALE.equals(Gender.FEMALE) ); // true
        System.out.println( Gender.FEMALE.equals(AttendType.ABSENT) ); // false
        
    • == operator
      • Same as compareTo(), but returns boolean instead of integer.
      • Example:
        System.out.println( Gender.MALE == Gender.FEMALE ); // false
        System.out.println( Gender.FEMALE == Gender.FEMALE); // true
        // System.out.println( Gender.FEMALE == AttendType.ABSENT ); // compile error
        
  • Which way should we use?

    • If enum type is fixed use ==. It will conver most of the cases.
    • Otherwise use equals() if you don't know the type.
    • When do we use compareTo() then? Find yourself or ignore.

Some basic operations

  • Reverse lookup using name or ordinal:

    • using valueOf(String) or values()[ordinal]:
      System.out.println( Gender.valueOf("MALE") ); // MALE
      System.out.println( Gender.values()[1]); // FEMALE
      
  • Finding all enum constant:

    • using EnumSet.allOf(EnumName.class)
    System.out.println( EnumSet.allOf(Gender.class) ); // [MALE, FEMALE]
    
  • Finding all enum constant within a range:

    • using EnumSet.range(START_ENUM, END_ENUM)
    System.out.println( EnumSet.range(MyWeekDay.SUNDAY, MyWeekDay.THURSDAY) );
    // [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY]
    
  • Finding all enum constant except some

    • using EnumSet.complementOf(list)
    EnumSet<MyWeekDay> holidays = EnumSet.of(MyWeekDay.SATURDAY, MyWeekDay.SUNDAY);
    System.out.println( EnumSet.complementOf(holidays) );
    // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
    

The next one is not that important. You can skip

Enum with Abstract method and interface

  • An enum can implement interface and can have abstract methods.
  • But we have to provide implementation in each constant for the abstract method.
    public interface Executable {
        void execute();
    }
    
    public enum CommandList implements Executable{
        RUN{
            @Override
            public void doNothing() { }
        },
        JUMP{
            @Override
            public void doNothing() { }
        };
    
        @Override
        public void execute() {
            if(this.equals(RUN)){
                System.out.println("Running");
            }
            else if(this.equals(JUMP)){
                System.out.println("Jumping");
            }
        }
        public abstract void doNothing();
    }
    
  • Example usage:
    CommandList.RUN.execute(); // Running
    CommandList.JUMP.execute(); // Jumping
    
User12024-11-02

This is a comment 1.

User12024-11-02

This is a comment 2.