How to use enumeration to eliminate if/else in Java

Keywords: Java

Today, I'm going to relearn enumeration types in Java.

Why study again now? Because when I first started learning Java, I didn't pay much attention to enumeration. After work, I basically didn't use enumeration. As a result, I don't quite understand the data type of enumeration. Sometimes when I see the enumeration types and related operations used in other people's code, I think they are very good, so I have the impulse to learn again.

Don't say much, start learning!

definition

What does enumeration mean? Baidu Encyclopedia says this:

In mathematical and computer science theory, enumeration of a set is a program that lists all members of some finite sequence set, or a count of a specific type of object. The two types often (but not always) overlap. Is a collection of named integer constants.

Enumerations are common in daily life. For example, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY and SATURDAY are enumerations.

By mapping this to the Java language, you can define an enumeration class representing the week:

public enum Week {

    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY

}

The keyword defining the enumeration class is enum,
Enumerating class objects can't be found through new. The SUNDAY and MONDAY in them are actually instances of enumerating class Week. These are the only fixed instances. You cannot create new instances externally. Direct class and instance name when referencing

Week w = Week.MONDAY;

constructor

Enumeration classes also have constructors, which are modified by private by default, and can only be private. Observe this Code:

public enum Week {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;

    Week(){
        System.out.println("hello");
    }

}

public class Test {
    public static void main(String[] args) {
        Week w = Week.FRIDAY;
    }
}

You will find this result:

hello

hello

hello

hello

hello

hello

hello

The constructor is executed seven times, which corresponds to the number of enumerated items in the class. In fact, the creation of this kind of enumeration item is equivalent to other classes calling the object from the parameterless constructor new, that is, this enumeration class has created 7 instances, so 7 hello s are output.

In addition to parameterless constructors, enumeration classes also have parameterless constructors.

public enum Week {
    SUNDAY(7), MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6);

    Week(int weekNum){
        System.out.println(weekNum);
    }

}

This time will output:

7

1

2

3

4

5

6

Enumerating class members

Like normal classes, enumeration classes can also have member variables, instance methods, static methods, etc.

public enum Week {
    SUNDAY(7), MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6);

    private int weekNum;

    Week(int weekNum){
        this.weekNum = weekNum;
    }

    public int getWeekNum() {
        return weekNum;
    }

}

use:

public class Test {
    public static void main(String[] args) {
        Week w = Week.FRIDAY;
        System.out.println(w.getWeekNum());
    }
}

Output:

5

Enumeration classes can also have abstract methods.

public enum Week {
    SUNDAY(){
        @Override
        public void getWeekNum() {
            System.out.println(7);
        }
    },
    MONDAY() {
        @Override
        public void getWeekNum() {
            System.out.println("Monday");
        }
    },

    TUESDAY(){
        @Override
        public void getWeekNum() {
            System.out.println("Tuesday");
        }
    },
    WEDNESDAY(){
        @Override
        public void getWeekNum() {
            System.out.println("Wednesday");
        }
    };

    public abstract void getWeekNum();
}

public class Test {
    public static void main(String[] args) {
        Week w = Week.TUESDAY;
        w.getWeekNum();
    }
}

Output:

Tuesday

values(), valueOf(String name) methods

Each enumeration class has two static methods:

  • static Direction[] values(): returns all enumeration constants of this class;

  • static Direction valueOf(String name): returns the Direction constant by enumerating the name of the constant. Note that this method has different parameters from the valueOf() method in Enum class.

public class Test {
    public static void main(String[] args) {
        for (Week w : Week.values()) {
            System.out.println(w);
        }
        System.out.println("Sunday:" + Week.valueOf("SUNDAY"));
    }
}

The results are as follows:

SUNDAY

MONDAY

TUESDAY

WEDNESDAY

THURSDAY

FRIDAY

SATURDAY

SUNDAY: SUNDAY

Enumeration usage

1. Type constraints

I believe you must have defined constants to use them in the usual development process:

public class Discount {
    public static final double EIGHT_DISCOUNT = 0.8;

    public static final double SIX_DISCOUNT = 0.6;

    public static final double FIVE_DISCOUNT = 0.5;
}

In fact, there is no problem with such a definition, but if there is a method like this:

BigDecimal calculatePrice(double discount){
    //...
}

You need to pass in the commodity discount to calculate the price. If you use the above constant definition, there is no type constraint. You can pass in any value of double type, and the compiler will not issue a warning. If you use enumeration to define this situation, there will be stronger type constraints:

public enum Discount {
    EIGHT_DISCOUNT(0.8), SIX_DISCOUNT(0.6), FIVE_DISCOUNT(0.5);

    private double discountNum;

    Discount(double discountNum) {
        this.discountNum = discountNum;
    }

    double getDiscountNum(){
        return discountNum;
    }
}

use:

public class Test {
    public static void main(String[] args) {
        calculatePrice(Discount.EIGHT_DISCOUNT);
    }

    static BigDecimal calculatePrice(Discount discount){
        System.out.println(discount.getDiscountNum());
        //...
        return null;
    }
}

0.8

2. Used in switch

public class Test {
    public static void main(String[] args) {
        Week w = Week.MONDAY;
        switch (w) {
            case MONDAY:
                System.out.println("Monday"); break;
            case TUESDAY:
                System.out.println("Tuesday"); break;
        }
    }
}

Monday

3. Implement the interface and eliminate if/else

The enumeration class we created is modified by final by default, and inherits the Enum class by default. Therefore, you can no longer inherit other classes. But you can implement the interface.

There is such a judgment scenario.

if ("dog".equals(animalType)){
    System.out.println("Eat bones");
} else if ("cat".equals(animalType)) {
    System.out.println("Eat dried fish");
} else if ("sheep") {
    System.out.println("graze");
}

How to eliminate if/else by enumerating? See the following code:

First define an interface with a general method eat()

public interface Eat {
    //eat
    String eat();
}

Then create an enumeration class to implement this interface

public enum AnimalEnum implements Eat {

    Dog(){
        @Override
        public void eat() {
            System.out.println("Eat bones");
        }
    },

    Cat() {
        @Override
        public void eat() {
            System.out.println("Eat dried fish");
        }
    },

    Sheep() {
        @Override
        public void eat() {
            System.out.println("graze");
        }
    }

}

Only one line of code is required when calling:

public class Test {
    public static void main(String[] args) {
        AnimalEnum.valueOf("Cat").eat();
    }
}

Eat dried fish

And in this way, if I want to expand new animals in the future, I just need to add code to the enumeration class without changing any old code, which is in line with the opening and closing principle!

4. Application in singleton mode

Enumeration can also be used in an implementation of singleton mode.

/**
 * @Author:
 * @Description: Enumerating thread safety
 */
public class SingletonExample {

    /**
     * Constructor is privatized to avoid external instance creation
     */
    private SingletonExample(){}

    private static SingletonExample getInstance() {
        return Singleton.INSTANCE.getInstance();
    }

    private enum Singleton {
        INSTANCE;
        private SingletonExample instance;

        // The JVM guarantees that this method is absolutely called only once
        Singleton() {
            instance = new SingletonExample();
        }

        public SingletonExample getInstance() {
            return instance;
        }
    }
}

summary

In fact, Java also has collection classes for enumeration, EnumSet and EnumMap, which we won't describe here.

I've learned a lot.

Posted by Agtronic on Sat, 27 Nov 2021 20:59:13 -0800