Friday, July 9, 2021

The Ultimate Guide of Enum in Java - Examples

Apart from the Class and Interface, Enumeration type or Enum is another popular type in Java programming language. Enum allows you to represent a fixed number of well-known things in a type-safe manner e.g. days of the week, days of the month, planets in the solar system, buttons on the remote control, keys on the keyboard, and suits on playing cards. Before Enum was introduced, prior to Java 1.5, integer and string constants are used to represent the fixed number of things, known as enum int pattern and enum string pattern as described in classic Effective Java by none other than Joshua Bloch. Though they served the purpose, they had some major drawbacks which resulted in poor quality code.


One of the major issues was type-safety i.e. you cannot restrict them to represent a fixed number of values like an integer constant, which is representing days of the week can have a value of 100, which is incorrect, given we have only 7 days in a week.

These limitations are addressed by providing an enum type, which guarantees that only a correct and fixed number of values can be assigned to them. The good thing about Enum in Java is that they are feature-rich, the bad thing is that they are still under-used and many developers don't even know about Enumeration type in detail.

Though there is a lot of blog post about different features of Enum in Java, and their usage, there is hardly any page, which provides a good look at key points about Enum. It doesn't mean to be comprehensive but at least provides those lesser-known details.

I had previously shared some features in form of question-answer in my article 15 Java Enum Interview Questions and in this post, we will learn more about Enum in Java in this article. I have kept the explanation short and to the point to it may look like a summary and notes than a tutorial, but can be very useful to quickly get up-to-speed with Enum type in Java.




The Ultimate Enum Tutorial in Java with Examples

Without wasting any more of your time, let's dive into the beautiful world of Enum in Java. After going through this guide, you will not only learn powerful Enum features in Java but also learn how to use Enum with full potential. 

1. Constant
Enum is constants in Java. They are implicitly declared public, static, and final. Since they are constant, there is no way you can change them.


2. Parent class
All enumeration type implicitly extends from java.lang.Enum class internally. This means Enums are internally represented as a class type. Furthermore, enum constants are instances of the enumeration class.

There is a lot of similarity between enum and class in Java but there is also some difference like enum instances are implicitly public static final, you don't need to declare them, as explained in The Complete Java Masterclass and shown in the following slide :

Difference between Enum and Class in Java




3. Enum and Classes
Since all Enum type extends java.lang.Enum, they cannot extend any other class in Java, as multiple inheritances are not allowed in Java, and a class can only extend one class. This property has not changed even with the introduction of default or defender methods in Java 8, which allows you to declare non-abstract methods in the interface.


4. Enum and Interface
Enum can implement an interface in Java, which is also a way to extend the enum type. When an Enum extend an interface, each of their instance implement interface method in their own way or you can provide a default implementation under Enum class itself.

Take a look at this example, it's not the best but at least demonstrates how to implement an interface inside enum in Java.

public class EnumDemo04{

        public static void main(String args[]) {

                EnumThread thread = EnumThread.ONE;
                thread.run();

                thread = EnumThread.TWO;
                thread.run();

                thread = EnumThread.THREE;
                thread.run();

        }

       

        private enum EnumThread implements Runnable{

            ONE {
                @Override
                public void run() {
                       System.out.println("ONE");
                }
            },

            TWO {
                @Override
                public void run() {
                       System.out.println("TWO");
                }
            },

            THREE;

                @Override
                public void run() {
            System.out.println("Default");

                }
        }
}

Output
ONE
TWO
Default

You can see that EnumThread, which is an enum actually implements the Runnable interface and also overrides the run() method. This proves that the enumeration type cannot only implement an interface but also can override methods in Java. You can further see these free Java Programming and Development courses to learn more about them.

Java Enum Tutorial - 10 Things Java Devs Should Know about Enumeration Type



5.  Enum and Constructor
An Enum class can have a constructor but it can only be private. You cannot make it public because Enum instances are supposed to be created at compile-time and from the class itself.

A non-private Enum constructor with any modifier other than private is a compile-time error in Java. Though a constructor without any access modifier is also allowed.

Similarly, you can also overload constructor inside Enum, as shown below, by the way, don't forget to declare enum constants or; before declaring constructors, you can also see this post to learn more about Enum constructor in Java.

public enum EnumWithConstructor {
    private EnumWithConstructor(){
      System.out.println("Default no-arg Enum constructor");
    }             

    EnumWithConstructor(int i){
       System.out.println("Enum Constructor with one argument");
    }
        
    // compile time error - illegal access modifier, 
     // only private is allowed
    public EnumWithConstructor(String s){
     System.out.println("public constructor 
          are not allowed inside Enum in Java");
    }

}



6. Enum Methods - name, values, and valueOf
The java.lang.Enum defines several useful methods, which is available to all enumeration type in Java. You can use the name() method to get the name of any Enum constants. String literal used to write enum constants are their name.

Similarly, the values() method can be used to get an array of all Enum constants from an Enum type and you can use the valueOf() method to convert any String to Enum constant in Java, as shown below

public class EnumDemo06{

        public static void main(String args[]) {
          Gender fromString =  Gender.valueOf("MALE");
          System.out.println("Gender.MALE.name() : " 
                + fromString.name());
        }      

        private enum Gender{
                MALE, FEMALE;
        }

}

Output:
Gender.MALE.name() : MALE

In this code snippet, valueOf() method returns an Enum constant Gender.MALE, calling name on that returns "MALE".



7.  Comparing Enums
 There are two ways to compare enum constants in Java, you can either use the equals() method or simply == operator. There are some advantages of using == operator over equals, as it provides type-safety and also avoids potential NullPointerException if the enum on which you are calling equals() is null. You can see more details about comparing two Enums in Java here.


8. Cloning Enum Constants
Enum constants cannot be cloned in Java. An attempt to make a clone of Enum constants will throw CloneNotSupportedException.



9. Enum in Switch Case
Like int, short and char, and String from Java 7, Enum can also be used inside switch and case statements, as shown below. You can also see this post to learn more about Enum and switch case in Java :

public class EnumDemo9{      

        public static void main(String args[]) {                            

        SmartPhone iPhone = new SmartPhone(SmartPhone.OS.iOS);
        SmartPhone.OS operatingSystem = iPhone.getOS();               

         switch(operatingSystem){
                case iOS:
                        System.out.println("Running on iOS");
                        break;                     

                case Android:
                        System.out.println("Running on Android");
                        break;

                case Windows8:
                        System.out.println("Running on Windows8");
                        break;
                }
        } 

}

class SmartPhone {       

        public enum OS{
                iOS, Android, Windows8;
        }

        private OS os;     

        public SmartPhone(OS os){
                this.os = os;          
        }   

        public OS getOS(){
                return os;

        }
}

Output:
Running on iOS
You can clearly say that we are using an enum variable inside the switch() block to decision making, and we are also using enum constants in case statements. You can further see these advanced core Java courses to learn more about the more advanced and effective use of Enum like this.

The Ultimate Guide of Enum in Java - Examples




10. Enum as Class variable
When you declare an Enum type inside a class, it is by default static. You can see that from the above example, we can access OS Enum type as SmartPhone.OS, which is like accessing a static member of any class.


11. Enum and new() operator
The new() operator is not permitted to be used with an enum, not even inside the enum itself. This is because, Enum constants are fixed, and no instance of an enum can be created at runtime.


12.Overring methods in Enum
 Like any other class, you can also override the toString() method for any Enum type. By default toString() method returns the name of Enum constants and its output is the same as of name() method, but you can override it to provide more information.

That's all about Enum in Java. I hope this detail helps you to understand the Enumeration type in Java. It's one of the fundamental concepts, which you can't afford to overlook. Since I have used Java even before the enumeration type exists, I can say that enum helps you to write robust and clean code in Java.


Here are other Java Enum Tutorials you may like:
  1. Java enum concepts and fundamentals for beginners (see here)
  2. How to convert Enum to String in Java  (click here)
  3. How to use enum in switch case in Java (see here)
  4. How to loop over Enum constants using a foreach loop in Java (link)
  5. How to use valueOf() method of Enum in Java (read here)
  6. How to create enum from String in Java (read here)
  7. Practical Example of Enum in Java (see here)
  8. How to define a constructor for Enumeration type (read here)
  9. How to implement Singleton pattern using Enum in Java (check here)
  10. Difference between RegularEnumSet and JumboEnumSet (read here)
  11. 15 Questions to check your knowledge about Enum in Java (answers)

Thanks for reading this article so far. If you like this article then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note. 

5 comments:

  1. The line :
    Gender fromString = Gender.MALE.valueOf("MALE");

    should be corrected to :

    Gender fromString = Gender.valueOf("MALE");

    ReplyDelete
  2. I am going through Enums that were introduced in Java 1.5. In Effective Java 2'nd Edition it's mentioned that before Java 1.5 there were int and String enum patterns which were having some deficiencies.

    I understood the cons of int enum patterns but while going through String enum patterns I got the basic idea but didn't get the deep sense of below statements mentioned under Item30 in Effective Java:

    This variant, known as the String enum pattern, is even less desirable. While it does provide printable strings for its constants, it can lead to performance problems because it relies on string comparisons. Worse, it can lead naive users to hard-code string constants into client code instead of using field names. If such a hard-coded string constant contains a typographical error, it will escape detection at compile time and result in bugs at runtime.

    Can anyone help me in understanding what these lines explaining. I would appreciate if it can be explained with some code snippet.

    Thanks

    ReplyDelete
    Replies
    1. It's simple, when you compare String compiler doesn't check for you whether the String is correct or not but with enum, compiler checks for you because Enum is always fixed

      For example, "INDEA".equals(getCountry())

      will compile fine even though there is typo and return false at runtime time but

      Country.INDEA == getCountr()

      will fail in compile time because there is no enum as "INDEA", you can see their is a typo in word INDEA ("E" instead of "I".) early detection of bug, typo, or mistake is what makes Java a language to learn.

      Delete

Feel free to comment, ask questions if you have any doubt.