Java: that’s the case with enumerating classes

1、 Foreword

This blog is about jdk1 5's new features are a wave of small summaries of enumeration, mainly because when I saw some interview questions yesterday, I met enumeration type questions and found that I have many details that need to be strengthened. They are ambiguous. It's time to summarize a wave.

2、 From an interview question

Not much BB, let's get straight to the point. I've come across a question that may be very simple:

enum AccountType
{
    SAVING,FIXED,CURRENT;
    private AccountType()
    {
        System.out.println(“It is a account type”);
    }
}
class EnumOne
{
    public static void main(String[]args)
    {
        System.out.println(AccountType.FIXED);
    }
}

What is the print result? The correct answer is as follows:

It is a account type
It is a account type
It is a account type
FIXED

As for why the result is this, let me summarize it slowly.

3、 Origin of enumeration

I like this Bible. Every time I can't explain why it appears, I unconsciously use this sentence.

Enumeration must have its value. Sometimes, we need to define a class. The objects in this class are limited and fixed. For example, we have four seasons a year, spring, summer, autumn and winter.

How do we define this season class before enumeration is supported? It might look like this:

public class Season {
    //private修饰构造器,无法随意创建对象
    private Season(){}
    //final修饰提供的对象在类外不能改变
    public static final Season SPRING = new Season();
    public static final Season SUMMER = new Season();
    public static final Season AUTUMN = new Season();
    public static final Season WINTER = new Season();
}

In terms of definition, this season class can fulfill our expectations. They each represent an instance and cannot be changed. External instances cannot be created casually.

However, there is a significant problem with the effect of enumerating through custom classes: the amount of code is very large.

Thus, jdk1 5. Enumeration class came into being.

4、 Definition form of enumeration

Enum keyword is used to define enumeration classes, which is equivalent to class and interface keywords. In other words, the enumeration class is not much different from the class we used before, and if the class modified by enum and class has the same name, an error will occur.

There are some rules that classes need to follow, and enumeration classes also follow:

There are also some rules. Enumeration classes are different:

After knowing this, we can redefine the enumeration class with enum keyword:

public enum Season{
    //定义四个实例
    SPRING,SUMMER,AUTUMN,WINTER;
}

5、 What's in the enum class?

Enum class is the top-level parent class of all enum classes modified by enum keyword. The methods defined in it are general by default. Let's take a look at it:

public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>,Serializable

We can find that enum is actually an abstract class inherited from the object class (the object class is indeed a top-level parent class and cannot be shaken), and implements two interfaces:

1. Unique constructor

    protected Enum(String name,int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

The official document says that programmers cannot call this constructor. It is used for the code issued by the compiler in response to the enum type declaration. We will understand this more deeply later.

2. Important methods

I won't repeat the methods in the object class here. I mainly mention the special methods.

Returns the name of this enumeration constant. Official advice: in most cases, it's best to use the toString () method because it can return a friendly name. The name () method is decorated with final and cannot be overridden.

From the source code point of view, the toString () method and the name () method are the same, but it is suggested that if there is a more friendly constant name display, you can override the toString () method.

Returns the ordinal number of this enumeration constant (its position in the enum declaration, where the ordinal number of the initial constant is zero).

Most programmers will not need this approach. It is used in complex enumeration based data structures, such as enumset and enummap.

This method is used to specify the comparison order of enumeration objects. The same enumeration instance can only be compared with enumeration instances of the same type.

    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            //getDeclaringClass()方法返回该枚举常量对应Enum类的类对象
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        //该枚举常量顺序在o常量之前,返回负整数
        return self.ordinal - other.ordinal;
    }

This static method returns the enumeration constant of the specified name in the specified enumeration class.

3. The values () method that appears out of thin air

Why do you think of summarizing this method? In fact, it also has a certain mental journey. The official document specially emphasizes the following sentence:

Generally, the things at the beginning of note are still more important. The general meaning is as follows:

After reading it, I didn't understand it, so I began to look up the data and found that there was a usage:

Arrays.asList(AccountType.values())

Obviously, the values () method of this enumeration class was called, but just now I analyzed the methods of the enumeration class, and I didn't see the values () method. But the compiler does prompt, yes, yes!

What's going on? The JDK document says:

When creating an enumeration class, the compiler will automatically add some special methods, such as the static values () method, which will return an array and store them in the order of enumeration constant declaration.

In this way, enumeration classes can be well matched with collections and other things. You will know how to match them in the future.

On this point, I will be more impressed after decompilation.

6、 Decompile enumeration class

Then, back to the interview question mentioned at the beginning of our article, we can infer what happens after the program runs according to the results:

At this point, our guess is over. In fact, it is not bad. This is roughly the process. After consulting the data, I tried to decompile the enumeration class file:

Let's start with javap - P accounttype The class Command tries to decompile and view all classes and members.

To see what happens in static, I try a more detailed instruction, javap - C - L accounttype Class, trying to get the local variable information table and line number, although I still can't understand it.

Let's take one of them as an example and refer to the virtual machine bytecode instruction table. The general process is as follows:

  static {};
    Code:
       0: new           #4                  //创建一个对象,将其引用值压入栈
       3: dup                               //复制栈顶数值并将复制值压入栈顶
       4: ldc           #10                 //将String常量值SAVING从常量池推送至栈顶
       6: iconst_0                          //将int型0推送至栈顶
       7: invokespecial #11                 //调用超类构造器
      10: putstatic     #12                 //为指定的静态域赋值

The following is a simplified compilation structure for personal understanding:

public final class AccountType extends java.lang.Enum<AccountType> {
    //静态枚举常量
    public static final AccountType SAVING;

    public static final AccountType FIXED;

    public static final AccountType CURRENT;

    //存储静态枚举常量的私有静态域
    private static final AccountType[] $VALUES;

    //编译器新加入的静态方法
    public static AccountType[] values();

    //调用实例方法获取指定名称的枚举常量
    public static AccountType valueOf(java.lang.String);

    static {
        //创建对象,传入枚举常量名和顺序
        SAVING = new AccountType("SAVING",0);
        FIXED = new AccountType("FIXED",1);
        CURRENT = new AccountType("CURRENT",2);
        //给静态域赋值
        $VALUES = new AccountType[]{
            SAVING,CURRENT
        }
    };     
}

The constructor of enum class will be called after sensing the class modified by enum keyword. The string literal value (name) and index (ordinal) of enumeration constant will be passed in. The created instance is stored in the private static field values.

And the compiler does add a static values () method to return an array of enumeration constants.

7、 Enumeration class implementation singleton

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}

This part will wait until the single case mode is summarized later, and first post an address at the end of the text.

8、 References

The enumeration and values () methods in Java assembly instructions are analyzed by javap command

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>