Sunday, June 20, 2021

Java Tutorial: enum Class

Chapters

Java enum Class

Reference: The Java™ Tutorials
Java enum is a special type of class that helps us create fixed set of constants which are called enum constants. Enum constants are variables that have values that can't be changed, just like final variables. Multiple enum constants must be separated by (,)comma.
public class SampleClass{

  public static void main(String[]args){
    //declaring enum references
    Jobs jobs = Jobs.SORT_DOCUMENTS;
    FileType type = FileType.TXT;
    
    //enum constants are instances of
    //their class.
    if(jobs instanceof Jobs)
      System.out.println("jobs is an instance "+
                         "of Jobs");
    if(type instanceof FileType)
      System.out.println("type is an instance "+
                         "of FileType");
  }
  
  //enum can be declared as inner class
  enum Jobs{
    //comma-separated constants
    SORT_DOCUMENTS,SORT_ZIP
  }
}

//enum can be declared as top-level class
enum FileType{
  //comma-separated constants
  TXT,PDF,ZIP
}
Note: enum constants are implicitly public, static and final by default.

enum Class Constructor

Like standard classes, enum class can have constructor. Though, we can't instantiate enum class. Enum constants are implicitly initialized with their class reference.
Example 

//This enum declaration
enum FileType{
  TXT,PDF,ZIP
}

//can be depicted like this
enum FileType{

  public static final FileType TXT = new FileType();
  public static final FileType PDF = new FileType();
  public static final FileType ZIP = new FileType();
}
Now, let's create an example to demonstrate enum constructor.
Note: Access modifier for enum constructor must be package-private(default) or private only.
public class SampleClass{

  public static void main(String[]args){
    int heroHP = BaseStats.HP.VALUE;
    int heroMP = BaseStats.MP.VALUE;
    int heroLvl = 1;
    
    if(heroLvl > 1){
      heroHP += 5 * heroLvl;
      heroMP += 10 * heroLvl;
    }
    
    System.out.println("Hero Level: " + heroLvl);
    System.out.println("Hero HP: " + heroHP);
    System.out.println("Hero MP: " + heroMP);
    System.out.println("Hero has taken percentage damage"
                      +" based on base stats!");
    System.out.println("HP and MP have been reduced!");
                      
    heroHP -= BaseStats.HP.percentDmgBase(.10f);
    heroMP -= BaseStats.MP.percentDmgBase(.25f);
    System.out.println("Hero HP: " + heroHP);
    System.out.println("Hero MP: " + heroMP);
    
  }
}

enum BaseStats{
  //java requires enum constants
  //to be defined first prior to any fields
  //or methods.
  //
  //When declaring enum constants with
  //constructor, don't forget to add 
  //parentheses() and also the semicolon(;)
  //at the end of the last enum constant.
  //
  //adding semicolon enables enum class for 
  //additional class members like variables
  //and methods. Try omitting the semicolon
  //here and you will encounter a convoluted error
  //
  //If the enum constructor has parameter-list
  //then the parentheses of enum constants must
  //have argument-lists that match the
  //parameter-list
  HP(1000),MP(500);
  
  final int VALUE;
  BaseStats(int value){
    VALUE = value;
  }
  
  int percentDmgBase(float percent){
    return (int)(VALUE * percent);
  }

}
Enum constructor won't instantiate its enum class constants until one of them is used.
public class SampleClass{

  public static void main(String[]args){
    System.out.println("SampleClass");
    //uncomment the codes below and the enum
    //constructor will instantiate its constants
    //FileType type1 = FileType.PDF;
    //System.out.println("type1: "+type1);
    
    //We can also get an enum constant
    //in another enum constant
    //FileType type2 = FileType.PDF.ZIP;
    //System.out.println("type2: "+type2);
  }
}

enum FileType{
  TXT(),PDF(),ZIP();
  
  FileType(){
    System.out.println(ordinal());
  }
}

java.lang.Enum in enum Class

java.lang.Enum class is implicitly inherited by enum class. That's why we can use some methods in java.lang.Enum. Let's create an example.
public class SampleClass{

  public static void main(String[]args){
  
    Task task = Task.MOVE;
    
    //ordinal() returns the constant position
    //in its enum declaration starting from 0
    System.out.println(task.ordinal());
    
    //name() returns the name of the constant
    String name = task.name();
    
    //or use toString()
    //String name = task.toString();
    
    System.out.println(name);
    
    //or directly use the reference in println()
    //'cause toString() has already been overriden
    //in enum class
    System.out.println("Object: " + task);
    //The result of this println() below is strange 
    //'cause toString() in object returns a hashcode-like
    //address of object
    System.out.println("Object: " + new SampleClass());
  }
}

enum Task{
  MOVE,COPY
}
Due to the fact that java.lang.Enum is implicitly inherited by enum class, enum class can't explicitly extend any class. Also, enum class can't be extended.

You might ask: "Object class is implicitly inherited by every class but classes can still explicitly extend a class then, Why enum class can't explicitly extend a class because java.alang.Enum is implicitly inherited?"

In my opinion, the reason is because implicit inheritance of java.lang.Enum in enum class has explicit effect whereas implicit inheritance of Object class in every class doesn't have explicit effect. This is just my opinion. Take it with a grain of salt.

values() Method in enum Class

In enum class, there's a static method that is implicitly defined and that method is the values() method. values() method returns an array of enum constants that are declared in an enum class.
public class SampleClass{

  public static void main(String[]args){
  
    for(Task task : Task.values())
      System.out.println(task);
  }
}

enum Task{
  MOVE,COPY,DELETE,MOVE_TO_TRASH
}

enum Constants in switch Block

We can use the enum constants as criteria in switch block.
public class SampleClass{

  public static void main(String[]args){
    DocumentType docType = DocumentType.PDF;
    
    //We don't need to include the enum class name
    //when using enum constants as criteria in switch
    //block
    switch(docType){
      
      case EPUB:
      System.out.println("Document Type is EPUB");
      break;
      
      case MOBI:
      System.out.println("Document Type is MOBI");
      break;
      
      case PDF:
      System.out.println("Document Type is PDF");
      break;
      
      case AZW3:
      System.out.println("Document Type is AZW3");
      break;
    }
    
  }
}

enum DocumentType{
  EPUB,MOBI,PDF,AZW3
}

Implementing Interface in enum Class

we know that enum classes can't extend classes. Though, enum classes can implement interfaces.
public class SampleClass{

  public static void main(String[] args){
    int heroHP = BaseStats.HP.VALUE;
    int heroMP = BaseStats.MP.VALUE;
    int heroLvl = 1;
    
    if(heroLvl > 1){
      heroHP += 5 * heroLvl;
      heroMP += 10 * heroLvl;
    }
    
    System.out.println("Hero Level: " + heroLvl);
    System.out.println("Hero HP: " + heroHP);
    System.out.println("Hero MP: " + heroMP);
    System.out.println("Hero has taken percentage damage"
                      +" based on base stats!");
    System.out.println("HP and MP have been reduced!");
                      
    heroHP -= BaseStats.HP.percentDmgBase(.10f);
    heroMP -= BaseStats.MP.percentDmgBase(.25f);
    System.out.println("Hero HP: " + heroHP);
    System.out.println("Hero MP: " + heroMP);
  }
}

interface ComputeDamage{

  int percentDmgBase(float percent);
}

//implementing interface in enum class
enum BaseStats implements ComputeDamage{
  HP(1000),MP(500);
  
  final int VALUE;
  BaseStats(int value){
    VALUE = value;
  }
  
  @Override
  public int percentDmgBase(float percent){
    return (int)(VALUE * percent);
  }

} 

No comments:

Post a Comment