Tutorial Java SCJP – #19 Enumerated lists or Enums

There are logically situations in which a variable must have values restricted to a specific range or set that is defined in the solution specifications. Let’s imagine that you must develop a Java applications that manages Vehicles and the engine type must take one value from the {GASOLINE, DIESEL, HYBRID, ELECTRICAL} set. You can define the engine type as a String or as an int and you can validate every time the input value. For strings you can compare the input value with “gasoline”, “diesel” and so on. For integer you can assume that GASOLINE is 1, DIESEL is 2, … and check the values based on this logic. This is a possible approach but it’s not ok because you can make easily mistakes and because you complicate a really simple procedure.

Starting with Java 5.0, the framework provides a more elegant solution to this problem by allowing programmers to define a predefined set of values, an enumerated list of values or enums. Moreover, programmers can define variables that will have values restricted to one from the enumerated list. And the compiler will overlook this by generating errors when the programmer will try to initialized the variable with a value outside the enum. Enumerated lists or enums can be seen as a new type of data which has a defined restriction regarding its possible values.

Other topics that are part of this Java tutorial are accessible through Java 6 Tutorial – Contents.

The concept behind enumerated list or enums isn’t something new in programming because other languages like C, C++, C# have also implemented this facility.

How to define and use enums

The most used (you will see later that enums are in fact classes and you can declare methods and attributes) syntax for declaring enums is

enum EnumName {constant1, constant2, ..., constantN};  //ATTENTION  the end ; (semicolon) is optional

Enums can be declared:

  • independently, globally as their own class;
  • inside another class;
  • NOT IN methods;

Going back to the vehicles scenario, the optimal solution is to declare an enum for the engine type like this:

//enumerated list declared as its own class
//REMEMBER the final ; is optional
enum EngineTypes{DIESEL,GASOLINE,HYBRID,ELECTRIC}

class Vehicle
{
    //enumerated list declared inside a class
    protected enum ColorTypes{RED, GREEN, BLUE, WHITE};

    //EngineTypes instance variable
    public EngineTypes engine;
    //ColorTypes instance variable
    public ColorTypes color;
}

When defining enums keep in mind:

  • enum symbols or constants are usually defined with caps (like DIESEL,GASOLINE, …) based on the Sun naming conventions;
  • enums symbols are not ints or Strings;
  • enums declared globally can be defined ONLY default or public (and NOT private or protected), but in this latter case in their own .java file (the same rule as for classes);
  • enums declared inside another class can have access modifiers (private, public, protected, default) which control its visibility outside the parent class (check Tutorial Java SCJP – #17 Access modifiers for methods and attributes);

As said before, enums are used to control the possible values of an variable. So if we want to initialize the engine instance variable values we must use only constants from the EngineTypes enum. For enums declared inside other classes the programmer must use the fully qualified name, which includes the parent class name.

public class Main {
    public static void main(String[] args) {
        Vehicle v = new Vehicle();
        v.engine = EngineTypes.DIESEL;

        //compiler errors:
        //v.engine = "DIESEL";  //error
        //v.engine = 1;         //error

	//fully qualified name given by class_name.enum_name.symbol
        v.color = Vehicle.ColorTypes.GREEN;
        //compiler error
        //v.color = ColorTypes.GREEN; //error
    }
}

One interesting characteristic of enums is that its symbols can be easily converted to a string value equal to the symbol. The next code sequence:

        System.out.println("The vehicle engine type is "+v.engine);
        
        String engineType = EngineTypes.ELECTRIC.toString();
        System.out.println("The engine type is "+engineType);

generates the messages:

The vehicle engine type is DIESEL
The engine type is ELECTRIC

Enums are classes in Java

In other languages like C or C++ enums are collections of symbols which have associated an unique numeric id. This description can’t be applied here, because in Java enums are classes and their symbols are static and constant instance variables  of the enum class. It is like saying that DIESEL is:

    //NOT valid in JAVA
    //just for your understanding of enums symbols
    public static final EngineTypes DIESEL = new EngineTypes("DIESEL");

Because enums are classes, it means that you can add to the enum (besides its symbols):

  • instance variables
  • methods
  • constructors

If we want to store inside an enum more than just the symbols, meaning  other values or some internal processing routines, we can use the fact that enums are classes in our favor.

Going back to the Vehicle scenario, let’s complicate things a little more:

  • we need a variable associated for each engine type that will store a unique numeric code;
  • we protect the code attribute by defining it private;
  • we define a method that will return the engine type code in order to just read it;
  • we need a constructor, as each EngineTypes symbol has its own unique code.

Based on previous rules, the EngineTypes enum is looking like this:

//enumerated list declared as its own class
//REMEMBER the final ; is optional
enum EngineTypes{
    //each symbol is created by calling the constructor
    DIESEL(10),GASOLINE(20),HYBRID(30),ELECTRIC(40);
    
    //enum instance variable for the code
    private int code;
    
    //enum constructor
    EngineTypes(int codeValue){
        code = codeValue;
    }

    //enum method
    public int getCode(){
        return code;
    }
// then enum end
}

Despite the fact EngineTypes enum looks like a class it’s not an usual one because:

  • public and protected access modifiers are NOT allowed for the constructor
  • you CAN’T create instances by calling directly the constructor (i.e. new EngineTypes(30));
  • the enums symbols must be the first declaration in the enumerated list;
  • you can call the constructor ONLY when defining enums symbols (i.e DIESEL(10)), even if the syntax is different and more similar to the C++ one;
  • you can overload enum constructors and define them with any number of parameters;

In this case, enums symbols behave like objects and you can call class methods. Variables of EngineTypes type represent references to the constant objects. The next sequence:

        System.out.println("The vehicle engine type is " + v.engine +
                " and its code is "+v.engine.getCode());

prints:

	The vehicle engine type is DIESEL and its code is 10

How to iterate through enums values

Each enumerated list provide a static method, values(),  used to iterate over the enums constants. The next sequence:

        System.out.println("The EngineTypes values are ");
        for(EngineTypes et : EngineTypes.values())
        {
            System.out.println(et + " with the code "+et.getCode());
        }

generates

The EngineTypes values are 
DIESEL with the code 10
GASOLINE with the code 20
HYBRID with the code 30
ELECTRIC with the code 40

What is constant specific class body

Enums are lists of constant objects that represents a limited set of values. Those values are significant in a very specific context. Despite enums are classes, programmers keep things very simple because enums are a special type of class with a very specific role. Most of enums methods, if any, are simple (like getters and setter) and provides generic solutions to the enums symbols.

If there are situations that require more than returning the attributes values, it is advised to create a new class and rethink the solutions architecture or to implement simple solutions.

For the previous example, let’s add a new specification:

  • the enum provides a method used to determine if the engine type pollutes or not;

If we analyze the engine types we can see that all are polluters with the except of the ELECTRIC one. So, the solution is to define a method that will test the engine type:

enum EngineTypes{
    //each symbol is created by calling the constructor
    DIESEL(10),GASOLINE(20),HYBRID(30),ELECTRIC(40);
    
    ...

    public boolean isPolluter()
    {
        if(this.toString().equals("ELECTRIC"))
            return false;
        else
            return true;
    }
// the enum end
}

As you can see, the code becomes little too complex for an enum. In order to keep things simple, Java provides another solution called constant specific class body. It represents situations in which programmers can define a particular method implementation for a particular enum constant or symbol.

In the previous example, we will define a overloaded form of the isPolluter() method particular to the ELECTRIC symbol.

//enumerated list declared as its own class
//REMEMBER the final ; is optional
enum EngineTypes{
    //each symbol is created by calling the constructor
    DIESEL(10),
    GASOLINE(20),
    HYBRID(30),
    ELECTRIC(40){
        //constant specific class body 
        //particular implementation of the method
        //overrides the generic implementation
        public boolean isPolluter(){
            return false;
        }
    };  //the semicolon is a MUST when code follows
    
    //enum instance variable for the code
    private int code;
    
    //enum constructor
    EngineTypes(int codeValue){
        code = codeValue;
    }

    //enum method
    public int getCode(){
        return this.code;
    }

    //the generic implementation
    public boolean isPolluter(){
            return true;
    }
}

In the previous example the isPolluter particular implementation for ELECTRIC symbol overrides the generic implementation providing a specific value.

For the SCJP exam remember:

  • an enum is a list of symbols which are not Strings, integer, … but constant values;
  • an enum type variable can be assigned ONLY with an enum symbols;
  • when declaring enums, the end semicolon (after the closing }) is optional;
  • enums are classes and can contain attributes, methods and constructors;
  • enums can be declared independently, globally as their own class, inside another class but NOT IN methods;
  • you CAN’T create instances by calling directly the constructor;
  • you can call the constructor ONLY when defining enums symbols (i.e DIESEL(10));
  • you can overload enum constructors and define them with any number of parameters;
  • the enum static method, values(), can be used to iterate over the enums constants;
  • enum symbols can have a constant specific class body used to override a generic method;

Other topics that are part of this Java tutorial are accessible through Java 6 Tutorial – Contents.