Netty series: I have an extensible Enum, do you want to take a look?

Get into the habit of writing together! This is the 26th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the event details .

Introduction

Many people have used enumeration in java. Enumeration is a new type referenced in JAVA 1.5 to represent the range that can be enumerated, but few people may know how enum in java works, enum and What does an Enum have to do with it? Can Enum be extended?

Let's take a look together.

enumEnum

The enumeration class was introduced in JAVA1.5, we usually use the enum keyword to define an enumeration class:

public enum StatusEnum {
    START(1,"start"),
    INPROCESS(2,"inprocess"),
    END(3,"end");

    private int code;
    private String desc;

    StatusEnum(int code, String desc){
        this.code=code;
        this.desc=desc;
    }
}
复制代码

In the above enumeration class, we have customized the constructor and defined 3 enumeration objects.

Let's see how to use this enumeration class:

    public static void main(String[] args) {
        StatusEnum start = START;
        System.out.println(start.name());
        System.out.println(start.ordinal());
        System.out.println(start.code);
        System.out.println(start.desc);
    }
复制代码

It is easy to understand that the code and desc can be output, because this is the attribute in our custom enumeration class, but what are the name and ordinal? Where did they come from?

Here we will introduce the java.lang.Enum class, which is the parent class of all enum enumeration classes in JAVA. The name() and ordinal() methods are defined in this class:

public final int ordinal() {
        return ordinal;
    }

public final String name() {
        return name;
    }
复制代码

Where ordinal represents the position of the enumeration in the enumeration class, then it is the name of the enumeration in the enumeration class. In the above example, the two values ​​of START are 1 and START respectively.

Let's take a look at the definition of the Enum class:

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable
复制代码

Enter it as an abstract class, but the compiler doesn't allow you to inherit from this class. If you force inheritance, it will throw an error:

Classes cannot directly extend 'java.lang.Enum'
复制代码

Therefore, strong twisted melons are not sweet, everyone must remember.

In fact, not only the Enum class itself cannot be inherited, but also the enum class StatusEnum created above.

What problem does this cause?

If the enum is contained in an external jar, you cannot extend the enum, and in some specific cases, this limitation may cause some inconvenience.

Fortunately, netty is also aware of this problem. Next, let's see how netty solves it.

Extensible Enum in netty: ConstantPool

The class representing constants in netty is called Constant, and it has two properties, ID and name:

public interface Constant<T extends Constant<T>> extends Comparable<T> {

    int id();

    String name();
}
复制代码

The one that stores these Constants is called ConstantPool. There is a ConcurrentMap in ConstantPool to save the specific Constant. Let's take a look at ConstantPool's factory class method valueOf:

public T valueOf(String name) {
        return getOrCreate(checkNonEmpty(name, "name"));
    }
复制代码

The valueOf method passes in the name of the created Constant. Then call the getOrCreate method to create a new Constant:

    private T getOrCreate(String name) {
        T constant = constants.get(name);
        if (constant == null) {
            final T tempConstant = newConstant(nextId(), name);
            constant = constants.putIfAbsent(name, tempConstant);
            if (constant == null) {
                return tempConstant;
            }
        }

        return constant;
    }
复制代码

You can see that getOrCreate is to create and get the newly created constant object from the constants Map.

Using ConstantPool

ConstantPool is an abstract class. If we need to create a new enumeration class pool, we can directly inherit ConstantPool and then implement the newConstant method. Here is a concrete example of usage:

public final class Foo extends AbstractConstant<Foo> {
  Foo(int id, String name) {
    super(id, name);
  }
}

public final class MyConstants {

  private static final ConstantPool<Foo> pool = new ConstantPool<Foo>() {
    @Override
    protected Foo newConstant(int id, String name) {
      return new Foo(id, name);
    }
  };

  public static Foo valueOf(String name) {
    return pool.valueOf(name);
  }

  public static final Foo A = valueOf("A");
  public static final Foo B = valueOf("B");
}

private final class YourConstants {
  public static final Foo C = MyConstants.valueOf("C");
  public static final Foo D = MyConstants.valueOf("D");
}
复制代码

In the above example, the enum class we created inherits from AbstractConstant, and then customizes ConstantPool, which can return the newly created Foo object from the pool.

In real time, ChannelOption, which is often used in netty channel, is a subclass of AbstractConstant. Let's briefly look at its implementation:

public class ChannelOption<T> extends AbstractConstant<ChannelOption<T>> {

    private static final ConstantPool<ChannelOption<Object>> pool = new ConstantPool<ChannelOption<Object>>() {
        @Override
        protected ChannelOption<Object> newConstant(int id, String name) {
            return new ChannelOption<Object>(id, name);
        }
    };
    public static <T> ChannelOption<T> valueOf(String name) {
        return (ChannelOption<T>) pool.valueOf(name);
    }
    public static <T> ChannelOption<T> valueOf(Class<?> firstNameComponent, String secondNameComponent) {
        return (ChannelOption<T>) pool.valueOf(firstNameComponent, secondNameComponent);
    }
    public static boolean exists(String name) {
        return pool.exists(name);
    }
    public static <T> ChannelOption<T> newInstance(String name) {
        return (ChannelOption<T>) pool.newInstance(name);
    }
复制代码

As you can see, ConstantPool is defined in ChannelOption, and then a new ChannelOption object is created through ConstantPool's valueOf and newInstance methods.

Summarize

If you also want to extend the enumeration class, try using Constant and ConstantPool.

Examples of this article can refer to: learn-netty4

Read more at www.flydean.com/49-netty-ex…

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!

Guess you like

Origin juejin.im/post/7090788611204841480